diff options
| author | Mitchell Johnson <ehntoo@ehntoo.org> | 2024-11-23 10:35:51 -0500 |
|---|---|---|
| committer | Mason Reed <mason@vector35.com> | 2024-12-05 10:38:58 -0500 |
| commit | 11b8d5ed652e65eb76e94af6a3aaf1e5835e7098 (patch) | |
| tree | cfd847af5c0026060ea416eb4f47e3d60e22031e /view/elf | |
| parent | 505febd772b0cba1e49f25d342216435196d10fd (diff) | |
Implement SHN_COMMON symbol handling
Diffstat (limited to 'view/elf')
| -rw-r--r-- | view/elf/elfview.cpp | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/view/elf/elfview.cpp b/view/elf/elfview.cpp index 78e31ad7..bf447a9a 100644 --- a/view/elf/elfview.cpp +++ b/view/elf/elfview.cpp @@ -1201,8 +1201,48 @@ bool ElfView::Init() combinedSymbolTable.insert(combinedSymbolTable.end(), dynamicSymbolTable.begin() + 1, dynamicSymbolTable.end()); if (auxSymbolTable.size() > 1) combinedSymbolTable.insert(combinedSymbolTable.end(), auxSymbolTable.begin() + 1, auxSymbolTable.end()); + + // Walk the symbol table a first time to collect the information we need to create a .common section + size_t commonSectionSize = 0; for (auto entry = combinedSymbolTable.begin(); entry != combinedSymbolTable.end(); entry++) { + if (entry->section == ELF_SHN_COMMON) + { + // account for required alignment, stored in entry->value; + auto alignedExistingSize = commonSectionSize + (entry->value - 1); + alignedExistingSize &= ~(entry->value - 1); + commonSectionSize = alignedExistingSize + entry->size; + } + } + + // If the common section exists create a mock segment/section. + size_t commonSegmentStartAddr = 0; + if (commonSectionSize > 0) { + // Find the end of the existing segment definitions to stick the SHN_COMMON segment + for (const auto& segment : GetSegments()) { + if (commonSegmentStartAddr < segment->GetEnd()) { + commonSegmentStartAddr = segment->GetEnd(); + } + } + // Align the common segment to 16 bytes + commonSegmentStartAddr = (commonSegmentStartAddr + 0xf) & (~0xf); + AddAutoSegment(commonSegmentStartAddr, commonSectionSize, 0, 0, SegmentReadable | SegmentWritable); + AddAutoSection(".common", commonSegmentStartAddr, commonSectionSize, ReadWriteDataSectionSemantics); + } + + size_t commonSegmentOffset = 0; + for (auto entry = combinedSymbolTable.begin(); entry != combinedSymbolTable.end(); entry++) + { + if (entry->section == ELF_SHN_COMMON) + { + // Common symbols are special as their entry value holds the alignment of the entry instead of an offset. + auto alignedExistingOffset = commonSegmentOffset + (entry->value - 1); + alignedExistingOffset &= ~(entry->value - 1); + DefineElfSymbol(DataSymbol, entry->name, commonSegmentStartAddr + alignedExistingOffset, false, entry->binding, entry->size); + commonSegmentOffset = alignedExistingOffset + entry->size; + continue; + } + if (m_objectFile) { if (entry->section >= m_elfSections.size()) |
