Correctly handle N_INDR nlist entries and don't rely on the trie information in order to reproduce them since this dyld trie info can be missing.

<rdar://problem/19749670>

llvm-svn: 229201
This commit is contained in:
Greg Clayton 2015-02-14 00:51:13 +00:00
parent 845af6c46d
commit 60038bebf1
3 changed files with 115 additions and 32 deletions

View File

@ -131,7 +131,7 @@ public:
FileSpec FileSpec
GetReExportedSymbolSharedLibrary () const; GetReExportedSymbolSharedLibrary () const;
bool void
SetReExportedSymbolName(const ConstString &name); SetReExportedSymbolName(const ConstString &name);
bool bool

View File

@ -2751,6 +2751,11 @@ ObjectFileMachO::ParseSymtab ()
nlist_data_offset = local_symbols_info.nlistOffset + (nlist_byte_size * local_symbols_entry.nlistStartIndex); nlist_data_offset = local_symbols_info.nlistOffset + (nlist_byte_size * local_symbols_entry.nlistStartIndex);
uint32_t string_table_offset = local_symbols_info.stringsOffset; uint32_t string_table_offset = local_symbols_info.stringsOffset;
typedef std::map<ConstString, uint16_t> UndefinedNameToDescMap;
typedef std::map<uint32_t, ConstString> SymbolIndexToName;
UndefinedNameToDescMap undefined_name_to_desc;
SymbolIndexToName reexport_shlib_needs_fixup;
for (uint32_t nlist_index = 0; nlist_index < local_symbols_entry.nlistCount; nlist_index++) for (uint32_t nlist_index = 0; nlist_index < local_symbols_entry.nlistCount; nlist_index++)
{ {
///////////////////////////// /////////////////////////////
@ -2791,6 +2796,7 @@ ObjectFileMachO::ParseSymtab ()
bool is_debug = ((nlist.n_type & N_STAB) != 0); bool is_debug = ((nlist.n_type & N_STAB) != 0);
bool demangled_is_synthesized = false; bool demangled_is_synthesized = false;
bool is_gsym = false; bool is_gsym = false;
bool set_value = true;
assert (sym_idx < num_syms); assert (sym_idx < num_syms);
@ -3147,9 +3153,30 @@ ObjectFileMachO::ParseSymtab ()
switch (n_type) switch (n_type)
{ {
case N_INDR: // Fall through case N_INDR:
case N_PBUD: // Fall through {
const char *reexport_name_cstr = strtab_data.PeekCStr(nlist.n_value);
if (reexport_name_cstr && reexport_name_cstr[0])
{
type = eSymbolTypeReExported;
ConstString reexport_name(reexport_name_cstr + ((reexport_name_cstr[0] == '_') ? 1 : 0));
sym[sym_idx].SetReExportedSymbolName(reexport_name);
set_value = false;
reexport_shlib_needs_fixup[sym_idx] = reexport_name;
indirect_symbol_names.insert(ConstString(symbol_name + ((symbol_name[0] == '_') ? 1 : 0)));
}
else
type = eSymbolTypeUndefined;
}
break;
case N_UNDF: case N_UNDF:
{
ConstString undefined_name(symbol_name + ((symbol_name[0] == '_') ? 1 : 0));
undefined_name_to_desc[undefined_name] = nlist.n_desc;
}
// Fall through
case N_PBUD:
type = eSymbolTypeUndefined; type = eSymbolTypeUndefined;
break; break;
@ -3467,8 +3494,11 @@ ObjectFileMachO::ParseSymtab ()
sym[sym_idx].SetID (nlist_idx); sym[sym_idx].SetID (nlist_idx);
sym[sym_idx].SetType (type); sym[sym_idx].SetType (type);
sym[sym_idx].GetAddress().SetSection (symbol_section); if (set_value)
sym[sym_idx].GetAddress().SetOffset (symbol_value); {
sym[sym_idx].GetAddress().SetSection (symbol_section);
sym[sym_idx].GetAddress().SetOffset (symbol_value);
}
sym[sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc); sym[sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc);
if (symbol_byte_size > 0) if (symbol_byte_size > 0)
@ -3489,6 +3519,17 @@ ObjectFileMachO::ParseSymtab ()
break; // No more entries to consider break; // No more entries to consider
} }
} }
for (const auto &pos :reexport_shlib_needs_fixup)
{
const auto undef_pos = undefined_name_to_desc.find(pos.second);
if (undef_pos != undefined_name_to_desc.end())
{
const uint8_t dylib_ordinal = llvm::MachO::GET_LIBRARY_ORDINAL(undef_pos->second);
if (dylib_ordinal > 0 && dylib_ordinal < dylib_files.GetSize())
sym[pos.first].SetReExportedSymbolSharedLibrary(dylib_files.GetFileSpecAtIndex(dylib_ordinal-1));
}
}
} }
} }
} }
@ -3498,6 +3539,8 @@ ObjectFileMachO::ParseSymtab ()
// Must reset this in case it was mutated above! // Must reset this in case it was mutated above!
nlist_data_offset = 0; nlist_data_offset = 0;
#endif #endif
typedef std::set<ConstString> IndirectSymbols;
IndirectSymbols indirect_symbol_names;
if (nlist_data.GetByteSize() > 0) if (nlist_data.GetByteSize() > 0)
{ {
@ -3521,6 +3564,10 @@ ObjectFileMachO::ParseSymtab ()
nlist_idx = 0; nlist_idx = 0;
} }
typedef std::map<ConstString, uint16_t> UndefinedNameToDescMap;
typedef std::map<uint32_t, ConstString> SymbolIndexToName;
UndefinedNameToDescMap undefined_name_to_desc;
SymbolIndexToName reexport_shlib_needs_fixup;
for (; nlist_idx < symtab_load_command.nsyms; ++nlist_idx) for (; nlist_idx < symtab_load_command.nsyms; ++nlist_idx)
{ {
struct nlist_64 nlist; struct nlist_64 nlist;
@ -3570,7 +3617,7 @@ ObjectFileMachO::ParseSymtab ()
bool is_gsym = false; bool is_gsym = false;
bool is_debug = ((nlist.n_type & N_STAB) != 0); bool is_debug = ((nlist.n_type & N_STAB) != 0);
bool demangled_is_synthesized = false; bool demangled_is_synthesized = false;
bool set_value = true;
assert (sym_idx < num_syms); assert (sym_idx < num_syms);
sym[sym_idx].SetDebug (is_debug); sym[sym_idx].SetDebug (is_debug);
@ -3927,9 +3974,30 @@ ObjectFileMachO::ParseSymtab ()
switch (n_type) switch (n_type)
{ {
case N_INDR:// Fall through case N_INDR:
case N_PBUD:// Fall through {
const char *reexport_name_cstr = strtab_data.PeekCStr(nlist.n_value);
if (reexport_name_cstr && reexport_name_cstr[0])
{
type = eSymbolTypeReExported;
ConstString reexport_name(reexport_name_cstr + ((reexport_name_cstr[0] == '_') ? 1 : 0));
sym[sym_idx].SetReExportedSymbolName(reexport_name);
set_value = false;
reexport_shlib_needs_fixup[sym_idx] = reexport_name;
indirect_symbol_names.insert(ConstString(symbol_name + ((symbol_name[0] == '_') ? 1 : 0)));
}
else
type = eSymbolTypeUndefined;
}
break;
case N_UNDF: case N_UNDF:
{
ConstString undefined_name(symbol_name + ((symbol_name[0] == '_') ? 1 : 0));
undefined_name_to_desc[undefined_name] = nlist.n_desc;
}
// Fall through
case N_PBUD:
type = eSymbolTypeUndefined; type = eSymbolTypeUndefined;
break; break;
@ -4249,8 +4317,11 @@ ObjectFileMachO::ParseSymtab ()
sym[sym_idx].SetID (nlist_idx); sym[sym_idx].SetID (nlist_idx);
sym[sym_idx].SetType (type); sym[sym_idx].SetType (type);
sym[sym_idx].GetAddress().SetSection (symbol_section); if (set_value)
sym[sym_idx].GetAddress().SetOffset (symbol_value); {
sym[sym_idx].GetAddress().SetSection (symbol_section);
sym[sym_idx].GetAddress().SetOffset (symbol_value);
}
sym[sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc); sym[sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc);
if (symbol_byte_size > 0) if (symbol_byte_size > 0)
@ -4266,6 +4337,18 @@ ObjectFileMachO::ParseSymtab ()
sym[sym_idx].Clear(); sym[sym_idx].Clear();
} }
} }
for (const auto &pos :reexport_shlib_needs_fixup)
{
const auto undef_pos = undefined_name_to_desc.find(pos.second);
if (undef_pos != undefined_name_to_desc.end())
{
const uint8_t dylib_ordinal = llvm::MachO::GET_LIBRARY_ORDINAL(undef_pos->second);
if (dylib_ordinal > 0 && dylib_ordinal < dylib_files.GetSize())
sym[pos.first].SetReExportedSymbolSharedLibrary(dylib_files.GetFileSpecAtIndex(dylib_ordinal-1));
}
}
} }
uint32_t synthetic_sym_id = symtab_load_command.nsyms; uint32_t synthetic_sym_id = symtab_load_command.nsyms;
@ -4458,19 +4541,24 @@ ObjectFileMachO::ParseSymtab ()
{ {
if (e.entry.import_name) if (e.entry.import_name)
{ {
// Make a synthetic symbol to describe re-exported symbol. // Only add indirect symbols from the Trie entries if we
if (sym_idx >= num_syms) // didn't have a N_INDR nlist entry for this already
sym = symtab->Resize (++num_syms); if (indirect_symbol_names.find(e.entry.name) == indirect_symbol_names.end())
sym[sym_idx].SetID (synthetic_sym_id++);
sym[sym_idx].GetMangled() = Mangled(e.entry.name);
sym[sym_idx].SetType (eSymbolTypeReExported);
sym[sym_idx].SetIsSynthetic (true);
sym[sym_idx].SetReExportedSymbolName(e.entry.import_name);
if (e.entry.other > 0 && e.entry.other <= dylib_files.GetSize())
{ {
sym[sym_idx].SetReExportedSymbolSharedLibrary(dylib_files.GetFileSpecAtIndex(e.entry.other-1)); // Make a synthetic symbol to describe re-exported symbol.
if (sym_idx >= num_syms)
sym = symtab->Resize (++num_syms);
sym[sym_idx].SetID (synthetic_sym_id++);
sym[sym_idx].GetMangled() = Mangled(e.entry.name);
sym[sym_idx].SetType (eSymbolTypeReExported);
sym[sym_idx].SetIsSynthetic (true);
sym[sym_idx].SetReExportedSymbolName(e.entry.import_name);
if (e.entry.other > 0 && e.entry.other <= dylib_files.GetSize())
{
sym[sym_idx].SetReExportedSymbolSharedLibrary(dylib_files.GetFileSpecAtIndex(e.entry.other-1));
}
++sym_idx;
} }
++sym_idx;
} }
} }
} }

View File

@ -209,18 +209,13 @@ Symbol::GetReExportedSymbolSharedLibrary() const
return FileSpec(); return FileSpec();
} }
bool void
Symbol::SetReExportedSymbolName(const ConstString &name) Symbol::SetReExportedSymbolName(const ConstString &name)
{ {
if (m_type == eSymbolTypeReExported) SetType (eSymbolTypeReExported);
{ // For eSymbolTypeReExported, the "const char *" from a ConstString
// For eSymbolTypeReExported, the "const char *" from a ConstString // is used as the offset in the address range base address.
// is used as the offset in the address range base address. m_addr_range.GetBaseAddress().SetOffset((uintptr_t)name.GetCString());
m_addr_range.GetBaseAddress().SetOffset((intptr_t)name.GetCString());
return true;
}
return false;
} }
bool bool
@ -230,7 +225,7 @@ Symbol::SetReExportedSymbolSharedLibrary(const FileSpec &fspec)
{ {
// For eSymbolTypeReExported, the "const char *" from a ConstString // For eSymbolTypeReExported, the "const char *" from a ConstString
// is used as the offset in the address range base address. // is used as the offset in the address range base address.
m_addr_range.SetByteSize((intptr_t)ConstString(fspec.GetPath().c_str()).GetCString()); m_addr_range.SetByteSize((uintptr_t)ConstString(fspec.GetPath().c_str()).GetCString());
return true; return true;
} }
return false; return false;