From 639673c536bfc82ee212bd3ffea02e88717cb4e2 Mon Sep 17 00:00:00 2001 From: Marc Aldorasi Date: Mon, 10 Jan 2022 12:52:14 -0500 Subject: Add function entries for non-contiguous functions --- src/cv2pdb.h | 2 +- src/dwarf2pdb.cpp | 111 +++++++++++++++++++++++++++++++++++++++--------------- src/mscvpdb.h | 15 ++++++++ 3 files changed, 96 insertions(+), 32 deletions(-) diff --git a/src/cv2pdb.h b/src/cv2pdb.h index 4b58140..ece2bdf 100644 --- a/src/cv2pdb.h +++ b/src/cv2pdb.h @@ -171,7 +171,7 @@ public: bool writeDWARFImage(const TCHAR* opath); bool addDWARFSectionContrib(mspdb::Mod* mod, unsigned long pclo, unsigned long pchi); - bool addDWARFProc(DWARF_InfoData& id, DIECursor cursor); + bool addDWARFProc(DWARF_InfoData& id, const std::vector &ranges, DIECursor cursor); int addDWARFStructure(DWARF_InfoData& id, DIECursor cursor); int addDWARFFields(DWARF_InfoData& structid, DIECursor cursor, int off); int addDWARFArray(DWARF_InfoData& arrayid, DIECursor cursor); diff --git a/src/dwarf2pdb.cpp b/src/dwarf2pdb.cpp index f53ae97..3220794 100644 --- a/src/dwarf2pdb.cpp +++ b/src/dwarf2pdb.cpp @@ -22,6 +22,58 @@ #include #include +// Returns all non-empty address ranges specified by id. The entry point (if applicable) is always the low address of the first range. +static std::vector getRanges(DIECursor cursor, const DWARF_InfoData &id) +{ + std::vector ret; + RangeEntry range; + if (id.pclo) + { + if (id.pchi == 0 || id.pchi == id.pclo) + return ret; + if (id.pclo < id.pcentry && id.pcentry < id.pchi) + { + range.pclo = id.pcentry; + range.pchi = id.pchi; + ret.push_back(range); + range.pclo = id.pclo; + range.pchi = id.pcentry; + ret.push_back(range); + } + else + { + range.pclo = id.pclo; + range.pchi = id.pchi; + ret.push_back(range); + } + } + else if (id.ranges != ~0) + { + RangeCursor rangeCursor(cursor, id.ranges); + while (rangeCursor.readNext(range)) + { + if (range.pclo == range.pchi) + continue; + if (range.pclo <= id.pcentry && id.pcentry < range.pchi) + { + std::uint64_t pclo = range.pclo; + range.pclo = id.pcentry; + ret.insert(ret.begin(), range); + if (pclo == id.pcentry) + { + range.pclo = pclo; + range.pchi = id.pcentry; + ret.push_back(range); + } + } + else + { + ret.push_back(range); + } + } + } + return ret; +} void CV2PDB::checkDWARFTypeAlloc(int size, int add) { @@ -643,10 +695,10 @@ void CV2PDB::appendLexicalBlock(DWARF_InfoData& id, unsigned int proclo) cbUdtSymbols += len; } -bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DIECursor cursor) +bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, const std::vector &ranges, DIECursor cursor) { - unsigned int pclo = procid.pclo - codeSegOff; - unsigned int pchi = procid.pchi - codeSegOff; + unsigned int pclo = ranges.front().pclo - codeSegOff; + unsigned int pchi = ranges.front().pchi - codeSegOff; unsigned int len; unsigned int align = 4; @@ -789,6 +841,26 @@ bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DIECursor cursor) appendEndArg(); appendEnd(); } + + for (std::size_t i=1; isepcode_v3.id = S_SEPCODE_V3; + cvs->sepcode_v3.len = sepcode_size - 2; + cvs->sepcode_v3.parent = 0; + cvs->sepcode_v3.end = 0; + cvs->sepcode_v3.length = ranges[i].pchi - ranges[i].pclo; + cvs->sepcode_v3.flags = 0; + cvs->sepcode_v3.offset = ranges[i].pclo - codeSegOff; + cvs->sepcode_v3.parent_offset = pclo; + cvs->sepcode_v3.section = img.text.secNo + 1; + cvs->sepcode_v3.parent_section = img.text.secNo + 1; + cbUdtSymbols += sepcode_size; + + appendEnd(); + } return true; } @@ -1453,42 +1525,19 @@ bool CV2PDB::createTypes() case DW_TAG_subprogram: if (id.name) { - if (!id.is_artificial) + std::vector ranges = getRanges(cursor, id); + if (!ranges.empty()) { - unsigned long entry_point = 0; - if (id.pcentry) - { - entry_point = id.pcentry; - } - else if (id.pclo) - { - entry_point = id.pclo; - } - else if (id.ranges != ~0) - { - entry_point = ~0; - RangeEntry range; - RangeCursor rangeCursor(cursor, id.ranges); - while (rangeCursor.readNext(range)) - { - entry_point = min(entry_point, range.pclo); - } - - if (entry_point == ~0) - entry_point = 0; - } - - if (entry_point) + if (!id.is_artificial) { + std::uint64_t entry_point = ranges.front().pclo; if (debug & DbgPdbSyms) fprintf(stderr, "%s:%d: Adding a public: %s at %x\n", __FUNCTION__, __LINE__, id.name, entry_point); mod->AddPublic2(id.name, img.text.secNo + 1, entry_point - codeSegOff, 0); } + addDWARFProc(id, ranges, cursor.getSubtreeCursor()); } - - if (id.pclo && id.pchi) - addDWARFProc(id, cursor.getSubtreeCursor()); } break; diff --git a/src/mscvpdb.h b/src/mscvpdb.h index b377a64..c6b4920 100644 --- a/src/mscvpdb.h +++ b/src/mscvpdb.h @@ -1670,6 +1670,20 @@ union codeview_symbol // return UDT,instance constructor,instance constructor with virtual base unsigned int unknown2; } funcinfo_32; + + struct + { + short int len; + short int id; + unsigned int parent; + unsigned int end; + unsigned int length; + unsigned int flags; + unsigned int offset; + unsigned int parent_offset; + short int section; + short int parent_section; + } sepcode_v3; }; #define S_COMPILAND_V1 0x0001 @@ -1745,6 +1759,7 @@ union codeview_symbol #define S_MSTOOL_V3 0x1116 /* compiler command line options and build information */ #define S_PUB_FUNC1_V3 0x1125 /* didn't get the difference between the two */ #define S_PUB_FUNC2_V3 0x1127 +#define S_SEPCODE_V3 0x1132 #define S_SECTINFO_V3 0x1136 #define S_SUBSECTINFO_V3 0x1137 #define S_ENTRYPOINT_V3 0x1138 -- cgit v0.12 From 7ec1f803f4c6a29706a5fa7110fb3706361217d0 Mon Sep 17 00:00:00 2001 From: Marc Aldorasi Date: Tue, 11 Jan 2022 09:52:43 -0500 Subject: Use the default msvc version instead of forcing v120_xp only for 32-bit release mode --- src/cv2pdb.vcxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cv2pdb.vcxproj b/src/cv2pdb.vcxproj index 47db26d..28c36a0 100644 --- a/src/cv2pdb.vcxproj +++ b/src/cv2pdb.vcxproj @@ -34,7 +34,7 @@ Application - v120_xp + $(DefaultPlatformToolset) Unicode true @@ -230,4 +230,4 @@ - \ No newline at end of file + -- cgit v0.12 From ab7dcd4bf8d756e07b49e94fc3de215a3ddcb32c Mon Sep 17 00:00:00 2001 From: Marc Aldorasi Date: Wed, 12 Jan 2022 13:08:51 -0500 Subject: Fixed improperly splitting a range containing the entry point --- src/dwarf2pdb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dwarf2pdb.cpp b/src/dwarf2pdb.cpp index 3220794..a2d7e07 100644 --- a/src/dwarf2pdb.cpp +++ b/src/dwarf2pdb.cpp @@ -59,7 +59,7 @@ static std::vector getRanges(DIECursor cursor, const DWARF_InfoData std::uint64_t pclo = range.pclo; range.pclo = id.pcentry; ret.insert(ret.begin(), range); - if (pclo == id.pcentry) + if (pclo != id.pcentry) { range.pclo = pclo; range.pchi = id.pcentry; -- cgit v0.12 From 4b53f1ec060f40111e4e68d5d21b73ceeb9da9a0 Mon Sep 17 00:00:00 2001 From: Marc Aldorasi Date: Fri, 14 Jan 2022 14:28:40 -0500 Subject: Added test for S_SEPCODE entries --- .github/workflows/build-and-test.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index ee2b5c4..00a03ec 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -61,3 +61,24 @@ jobs: curl -Lo cvdump.exe https://raw.githubusercontent.com/microsoft/microsoft-pdb/HEAD/cvdump/cvdump.exe && ./cvdump.exe world.pdb >world.cvdump && grep '^S_PUB32: .*, Flags: 00000000, main$' world.cvdump + - name: verify split functions + shell: bash + run: | + set -x && + cat >split.c <<-\EOF && + __attribute__((cold,noinline)) void cold() { volatile int i=0; } + __attribute__((dllexport)) void split_func(int i) + { + if (i) + cold(); + } + EOF + + gcc -g -O2 -shared -o split-dwarf.dll split.c && + bin/${{env.BUILD_CONFIGURATION}}*/cv2pdb.exe split-dwarf.dll split-cv.dll && + + ls -l split-dwarf* split-cv* && + + curl -Lo cvdump.exe https://raw.githubusercontent.com/microsoft/microsoft-pdb/HEAD/cvdump/cvdump.exe && + ./cvdump.exe split-cv.pdb > split-cv.dump && + awk '$2 == "S_GPROC32:" && $NF == "split_func" { scope=gensub(/,/,"",1,$3); } $2 == "S_SEPCODE:" { getline; if ($4 == scope) found=1; } END {exit !found; }' split-cv.dump -- cgit v0.12