Skip to content

Commit

Permalink
Merge pull request #71 from GroundControl-Solutions/non-contiguous-fu…
Browse files Browse the repository at this point in the history
…nctions

Support non-contiguous functions
  • Loading branch information
rainers authored Jan 24, 2022
2 parents f82a603 + 4b53f1e commit c99df6c
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 34 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion src/cv2pdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ class CV2PDB : public LastError
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<RangeEntry> &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);
Expand Down
4 changes: 2 additions & 2 deletions src/cv2pdb.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
Expand Down Expand Up @@ -230,4 +230,4 @@
</PropertyGroup>
<Error Condition="!Exists('packages\Microsoft.VisualStudio.Setup.Configuration.Native.1.16.30\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.VisualStudio.Setup.Configuration.Native.1.16.30\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets'))" />
</Target>
</Project>
</Project>
111 changes: 80 additions & 31 deletions src/dwarf2pdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,58 @@
#include <string>
#include <vector>

// 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<RangeEntry> getRanges(DIECursor cursor, const DWARF_InfoData &id)
{
std::vector<RangeEntry> 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)
{
Expand Down Expand Up @@ -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<RangeEntry> &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;
Expand Down Expand Up @@ -789,6 +841,26 @@ bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DIECursor cursor)
appendEndArg();
appendEnd();
}

for (std::size_t i=1; i<ranges.size(); ++i)
{
const int sepcode_size = sizeof(codeview_symbol::sepcode_v3);
checkUdtSymbolAlloc(sepcode_size);
codeview_symbol*cvs = (codeview_symbol*) (udtSymbols + cbUdtSymbols);
cvs->sepcode_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;
}

Expand Down Expand Up @@ -1453,42 +1525,19 @@ bool CV2PDB::createTypes()
case DW_TAG_subprogram:
if (id.name)
{
if (!id.is_artificial)
std::vector<RangeEntry> 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;

Expand Down
15 changes: 15 additions & 0 deletions src/mscvpdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit c99df6c

Please sign in to comment.