From 42b17f97cf4a9c1b63e3c4e7c62a79bd024728d8 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Thu, 6 Nov 2014 08:10:41 +0000 Subject: [PATCH] Object, COFF: Infer symbol sizes from adjacent symbols Use the position of the subsequent symbol in the object file to infer the size of it's predecessor. I hope to eventually remove whatever COFF specific details from this little algorithm so that we can unify this logic with what Mach-O does. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221444 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/COFFObjectFile.cpp | 46 +++++++++++++++++++++++++----- test/Object/nm-trivial-object.test | 12 ++++---- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 4fbb78254ea..7a0892dd98d 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -250,20 +250,52 @@ std::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref, return object_error::success; } } - // FIXME: Return the correct size. This requires looking at all the symbols - // in the same section as this symbol, and looking for either the next - // symbol, or the end of the section. + + // Let's attempt to get the size of the symbol by looking at the address of + // the symbol after the symbol in question. + uint64_t SymbAddr; + if (std::error_code EC = getSymbolAddress(Ref, SymbAddr)) + return EC; int32_t SectionNumber = Symb.getSectionNumber(); - if (!COFF::isReservedSectionNumber(SectionNumber)) { + if (COFF::isReservedSectionNumber(SectionNumber)) { + // Absolute and debug symbols aren't sorted in any interesting way. + Result = 0; + return object_error::success; + } + const section_iterator SecEnd = section_end(); + uint64_t AfterAddr = UnknownAddressOrSize; + for (const symbol_iterator &SymbI : symbols()) { + section_iterator SecI = SecEnd; + if (std::error_code EC = SymbI->getSection(SecI)) + return EC; + // Check the symbol's section, skip it if it's in the wrong section. + // First, make sure it is in any section. + if (SecI == SecEnd) + continue; + // Second, make sure it is in the same section as the symbol in question. + if (!sectionContainsSymbol(SecI->getRawDataRefImpl(), Ref)) + continue; + uint64_t Addr; + if (std::error_code EC = SymbI->getAddress(Addr)) + return EC; + // We want to compare our symbol in question with the closest possible + // symbol that comes after. + if (AfterAddr > Addr && Addr > SymbAddr) + AfterAddr = Addr; + } + if (AfterAddr == UnknownAddressOrSize) { + // No symbol comes after this one, assume that everything after our symbol + // is part of it. const coff_section *Section = nullptr; if (std::error_code EC = getSection(SectionNumber, Section)) return EC; - Result = Section->SizeOfRawData - Symb.getValue(); - return object_error::success; + } else { + // Take the difference between our symbol and the symbol that comes after + // our symbol. + Result = AfterAddr - SymbAddr; } - Result = 0; return object_error::success; } diff --git a/test/Object/nm-trivial-object.test b/test/Object/nm-trivial-object.test index 4ead46e153b..0135f2df3cb 100644 --- a/test/Object/nm-trivial-object.test +++ b/test/Object/nm-trivial-object.test @@ -1,6 +1,6 @@ -RUN: yaml2obj %p/Inputs/COFF/i386.yaml | llvm-nm -a - \ +RUN: yaml2obj %p/Inputs/COFF/i386.yaml | llvm-nm -a -S - \ RUN: | FileCheck %s -check-prefix COFF -RUN: yaml2obj %p/Inputs/COFF/x86-64.yaml | llvm-nm -a - \ +RUN: yaml2obj %p/Inputs/COFF/x86-64.yaml | llvm-nm -a -S - \ RUN: | FileCheck %s -check-prefix COFF RUN: llvm-nm %p/Inputs/trivial-object-test.elf-i386 \ RUN: | FileCheck %s -check-prefix ELF @@ -49,11 +49,11 @@ RUN: llvm-nm | FileCheck %s -check-prefix A-OUT REQUIRES: shell -COFF: 00000000 d .data -COFF: 00000000 t .text -COFF: 00000000 d L{{_?}}.str +COFF: 00000000 {{.*}} d .data +COFF: 00000000 {{.*}} t .text +COFF: 00000000 0000000d d L{{_?}}.str COFF: U {{_?}}SomeOtherFunction -COFF: 00000000 T {{_?}}main +COFF: 00000000 {{.*}} T {{_?}}main COFF: U {{_?}}puts COFF-COMMON: 00000000 00000000 b .bss -- 2.34.1