From: Jonas Devlieghere Date: Wed, 9 Oct 2019 04:16:18 +0000 (+0000) Subject: [dsymutil] Fix handling of common symbols in multiple object files. X-Git-Tag: llvmorg-11-init~7128 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4ac388f7caccc94065712878667829cebd7b8083;p=platform%2Fupstream%2Fllvm.git [dsymutil] Fix handling of common symbols in multiple object files. For common symbols the linker emits only a single symbol entry in the debug map. This caused dsymutil to not relocate common symbols when linking DWARF coming form object files that did not have this entry. This patch fixes that by keeping track of common symbols in the object files and synthesizing a debug map entry for them using the address from the main binary. Differential revision: https://reviews.llvm.org/D68680 llvm-svn: 374139 --- diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/common/com b/llvm/test/tools/dsymutil/Inputs/private/tmp/common/com new file mode 100755 index 0000000..3aec975 Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/private/tmp/common/com differ diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/common/com1.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/common/com1.o new file mode 100644 index 0000000..32c05ad Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/private/tmp/common/com1.o differ diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/common/com2.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/common/com2.o new file mode 100644 index 0000000..a22d1af Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/private/tmp/common/com2.o differ diff --git a/llvm/test/tools/dsymutil/X86/common-sym-multi.test b/llvm/test/tools/dsymutil/X86/common-sym-multi.test new file mode 100644 index 0000000..008362e --- /dev/null +++ b/llvm/test/tools/dsymutil/X86/common-sym-multi.test @@ -0,0 +1,39 @@ +RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/common/com -f -o - | llvm-dwarfdump -debug-info - | FileCheck %s +RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/common/com -dump-debug-map | FileCheck %s --check-prefix DEBUGMAP + +The test was compiled from two source files: +$ cd /private/tmp/common +$ cat com1.c +int i[1000]; +int main() { + return i[1]; +} +$ cat com2.c +extern int i[1000]; +int bar() { + return i[0]; +} +$ clang -fcommon -g -c com1.c -o com1.o +$ clang -fcommon -g -c com2.c -o com2.o +$ clang -fcommon -g com1.o com2.o -o com + +CHECK: DW_TAG_compile_unit +CHECK: DW_TAG_variable +CHECK-NOT: {{NULL|DW_TAG}} +CHECK: DW_AT_name{{.*}}"i" +CHECK-NOT: {{NULL|DW_TAG}} +CHECK: DW_AT_location{{.*}}DW_OP_addr 0x100001000) + +CHECK: DW_TAG_compile_unit +CHECK: DW_TAG_variable +CHECK-NOT: {{NULL|DW_TAG}} +CHECK: DW_AT_name{{.*}}"i" +CHECK-NOT: {{NULL|DW_TAG}} +CHECK: DW_AT_location{{.*}}DW_OP_addr 0x100001000) + +DEBUGMAP: filename:{{.*}}com1.o +DEBUGMAP: symbols: +DEBUGMAP: sym: _i, binAddr: 0x0000000100001000, size: 0x00000000 +DEBUGMAP: filename:{{.*}}com2.o +DEBUGMAP: symbols: +DEBUGMAP: sym: _i, binAddr: 0x0000000100001000, size: 0x00000000 diff --git a/llvm/tools/dsymutil/MachODebugMapParser.cpp b/llvm/tools/dsymutil/MachODebugMapParser.cpp index 27379c2..487fbff 100644 --- a/llvm/tools/dsymutil/MachODebugMapParser.cpp +++ b/llvm/tools/dsymutil/MachODebugMapParser.cpp @@ -14,6 +14,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" +#include namespace { using namespace llvm; @@ -51,6 +52,8 @@ private: StringRef MainBinaryStrings; /// The constructed DebugMap. std::unique_ptr Result; + /// List of common symbols that need to be added to the debug map. + std::vector CommonSymbols; /// Map of the currently processed object file symbol addresses. StringMap> CurrentObjectAddresses; @@ -81,6 +84,8 @@ private: STE.n_value); } + void addCommonSymbols(); + /// Dump the symbol table output header. void dumpSymTabHeader(raw_ostream &OS, StringRef Arch); @@ -122,11 +127,32 @@ void MachODebugMapParser::resetParserState() { CurrentDebugMapObject = nullptr; } +/// Commons symbols won't show up in the symbol map but might need to be +/// relocated. We can add them to the symbol table ourselves by combining the +/// information in the object file (the symbol name) and the main binary (the +/// address). +void MachODebugMapParser::addCommonSymbols() { + for (auto &CommonSymbol : CommonSymbols) { + uint64_t CommonAddr = getMainBinarySymbolAddress(CommonSymbol); + if (CommonAddr == 0) { + // The main binary doesn't have an address for the given symbol. + continue; + } + if (!CurrentDebugMapObject->addSymbol(CommonSymbol, None /*ObjectAddress*/, + CommonAddr, 0 /*size*/)) { + // The symbol is already present. + continue; + } + } + CommonSymbols.clear(); +} + /// Create a new DebugMapObject. This function resets the state of the /// parser that was referring to the last object file and sets /// everything up to add symbols to the new one. void MachODebugMapParser::switchToNewDebugMapObject( StringRef Filename, sys::TimePoint Timestamp) { + addCommonSymbols(); resetParserState(); SmallString<80> Path(PathPrefix); @@ -466,10 +492,15 @@ void MachODebugMapParser::loadCurrentObjectFileSymbols( // relocations will use the symbol itself, and won't need an // object file address. The object file address field is optional // in the DebugMap, leave it unassigned for these symbols. - if (Sym.getFlags() & (SymbolRef::SF_Absolute | SymbolRef::SF_Common)) + uint32_t Flags = Sym.getFlags(); + if (Flags & SymbolRef::SF_Absolute) { CurrentObjectAddresses[*Name] = None; - else + } else if (Flags & SymbolRef::SF_Common) { + CurrentObjectAddresses[*Name] = None; + CommonSymbols.push_back(*Name); + } else { CurrentObjectAddresses[*Name] = Addr; + } } }