Skip to content

Commit

Permalink
[dsymutil] Fix handling of common symbols in multiple object files.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
JDevlieghere committed Oct 9, 2019
1 parent 0746aaf commit 4ac388f
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 2 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
39 changes: 39 additions & 0 deletions llvm/test/tools/dsymutil/X86/common-sym-multi.test
Original file line number Diff line number Diff line change
@@ -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
35 changes: 33 additions & 2 deletions llvm/tools/dsymutil/MachODebugMapParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include <vector>

namespace {
using namespace llvm;
Expand Down Expand Up @@ -51,6 +52,8 @@ class MachODebugMapParser {
StringRef MainBinaryStrings;
/// The constructed DebugMap.
std::unique_ptr<DebugMap> Result;
/// List of common symbols that need to be added to the debug map.
std::vector<std::string> CommonSymbols;

/// Map of the currently processed object file symbol addresses.
StringMap<Optional<uint64_t>> CurrentObjectAddresses;
Expand Down Expand Up @@ -81,6 +84,8 @@ class MachODebugMapParser {
STE.n_value);
}

void addCommonSymbols();

/// Dump the symbol table output header.
void dumpSymTabHeader(raw_ostream &OS, StringRef Arch);

Expand Down Expand Up @@ -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<std::chrono::seconds> Timestamp) {
addCommonSymbols();
resetParserState();

SmallString<80> Path(PathPrefix);
Expand Down Expand Up @@ -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;
}
}
}

Expand Down

0 comments on commit 4ac388f

Please sign in to comment.