summaryrefslogtreecommitdiff
path: root/view/elf/elfview.cpp
diff options
context:
space:
mode:
authorMitchell Johnson <ehntoo@ehntoo.org>2024-11-23 10:35:51 -0500
committerMason Reed <mason@vector35.com>2024-12-05 10:38:58 -0500
commit11b8d5ed652e65eb76e94af6a3aaf1e5835e7098 (patch)
treecfd847af5c0026060ea416eb4f47e3d60e22031e /view/elf/elfview.cpp
parent505febd772b0cba1e49f25d342216435196d10fd (diff)
Implement SHN_COMMON symbol handling
Diffstat (limited to 'view/elf/elfview.cpp')
-rw-r--r--view/elf/elfview.cpp40
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())