<rdar://problem/11016907>
Get function boundaries from the LC_FUNCTION_STARTS load command. This helps to determine symbol sizes and also allows us to be able to debug stripped binaries. If you have a stack backtrace that goes through a function that has been stripped from the symbol table, the variables for any functions above that stack frame will most likely be incorrect. It can also affect our ability to step in/out/through of a function. llvm-svn: 152381
This commit is contained in:
parent
efbc7d2356
commit
f3bb3e472f
|
@ -18,6 +18,7 @@
|
|||
|
||||
namespace lldb_private {
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Templatized classes for dealing with generic ranges and also
|
||||
// collections of ranges, or collections of ranges that have associated
|
||||
|
@ -334,6 +335,22 @@ namespace lldb_private {
|
|||
return m_entries[i];
|
||||
}
|
||||
|
||||
Entry *
|
||||
Back()
|
||||
{
|
||||
if (m_entries.empty())
|
||||
return NULL;
|
||||
return &m_entries.back();
|
||||
}
|
||||
|
||||
const Entry *
|
||||
Back() const
|
||||
{
|
||||
if (m_entries.empty())
|
||||
return NULL;
|
||||
return &m_entries.back();
|
||||
}
|
||||
|
||||
static bool
|
||||
BaseLessThan (const Entry& lhs, const Entry& rhs)
|
||||
{
|
||||
|
@ -634,6 +651,36 @@ namespace lldb_private {
|
|||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
Entry *
|
||||
FindEntryThatContains (B addr)
|
||||
{
|
||||
#ifdef ASSERT_RANGEMAP_ARE_SORTED
|
||||
assert (IsSorted());
|
||||
#endif
|
||||
if ( !m_entries.empty() )
|
||||
{
|
||||
Entry entry;
|
||||
entry.SetRangeBase(addr);
|
||||
entry.SetByteSize(1);
|
||||
typename Collection::iterator begin = m_entries.begin();
|
||||
typename Collection::iterator end = m_entries.end();
|
||||
typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
|
||||
|
||||
if (pos != end && pos->Contains(addr))
|
||||
{
|
||||
return &(*pos);
|
||||
}
|
||||
else if (pos != begin)
|
||||
{
|
||||
--pos;
|
||||
if (pos->Contains(addr))
|
||||
{
|
||||
return &(*pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
const Entry *
|
||||
FindEntryThatContains (B addr) const
|
||||
{
|
||||
|
@ -713,6 +760,193 @@ namespace lldb_private {
|
|||
Collection m_entries;
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// A simple range with data class where you get to define the type of
|
||||
// the range base "B", the type used for the range byte size "S", and
|
||||
// the type for the associated data "T".
|
||||
//----------------------------------------------------------------------
|
||||
template <typename B, typename T>
|
||||
struct AddressData
|
||||
{
|
||||
typedef B BaseType;
|
||||
typedef T DataType;
|
||||
|
||||
BaseType addr;
|
||||
DataType data;
|
||||
|
||||
AddressData () :
|
||||
addr (),
|
||||
data ()
|
||||
{
|
||||
}
|
||||
|
||||
AddressData (B a, DataType d) :
|
||||
addr (a),
|
||||
data (d)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
operator < (const AddressData &rhs) const
|
||||
{
|
||||
if (this->addr == rhs.addr)
|
||||
return this->data < rhs.data;
|
||||
return this->addr < rhs.addr;
|
||||
}
|
||||
|
||||
bool
|
||||
operator == (const AddressData &rhs) const
|
||||
{
|
||||
return this->addr == rhs.addr &&
|
||||
this->data == rhs.data;
|
||||
}
|
||||
|
||||
bool
|
||||
operator != (const AddressData &rhs) const
|
||||
{
|
||||
return this->addr != rhs.addr ||
|
||||
this->data == rhs.data;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename B, typename T, unsigned N>
|
||||
class AddressDataArray
|
||||
{
|
||||
public:
|
||||
typedef AddressData<B,T> Entry;
|
||||
//typedef std::vector<Entry> Collection;
|
||||
typedef llvm::SmallVector<Entry, N> Collection;
|
||||
|
||||
|
||||
AddressDataArray ()
|
||||
{
|
||||
}
|
||||
|
||||
~AddressDataArray()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Append (const Entry &entry)
|
||||
{
|
||||
m_entries.push_back (entry);
|
||||
}
|
||||
|
||||
void
|
||||
Sort ()
|
||||
{
|
||||
if (m_entries.size() > 1)
|
||||
std::stable_sort (m_entries.begin(), m_entries.end());
|
||||
}
|
||||
|
||||
#ifdef ASSERT_RANGEMAP_ARE_SORTED
|
||||
bool
|
||||
IsSorted () const
|
||||
{
|
||||
typename Collection::const_iterator pos, end, prev;
|
||||
// First we determine if we can combine any of the Entry objects so we
|
||||
// don't end up allocating and making a new collection for no reason
|
||||
for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
|
||||
{
|
||||
if (prev != end && *pos < *prev)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
Clear ()
|
||||
{
|
||||
m_entries.clear();
|
||||
}
|
||||
|
||||
bool
|
||||
IsEmpty () const
|
||||
{
|
||||
return m_entries.empty();
|
||||
}
|
||||
|
||||
size_t
|
||||
GetSize () const
|
||||
{
|
||||
return m_entries.size();
|
||||
}
|
||||
|
||||
const Entry *
|
||||
GetEntryAtIndex (size_t i) const
|
||||
{
|
||||
if (i<m_entries.size())
|
||||
return &m_entries[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Clients must ensure that "i" is a valid index prior to calling this function
|
||||
const Entry &
|
||||
GetEntryRef (size_t i) const
|
||||
{
|
||||
return m_entries[i];
|
||||
}
|
||||
|
||||
static bool
|
||||
BaseLessThan (const Entry& lhs, const Entry& rhs)
|
||||
{
|
||||
return lhs.addr < rhs.addr;
|
||||
}
|
||||
|
||||
Entry *
|
||||
FindEntry (B addr, bool exact_match_only)
|
||||
{
|
||||
#ifdef ASSERT_RANGEMAP_ARE_SORTED
|
||||
assert (IsSorted());
|
||||
#endif
|
||||
if ( !m_entries.empty() )
|
||||
{
|
||||
Entry entry;
|
||||
entry.addr = addr;
|
||||
typename Collection::iterator begin = m_entries.begin();
|
||||
typename Collection::iterator end = m_entries.end();
|
||||
typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
|
||||
|
||||
if (pos != end)
|
||||
{
|
||||
if (pos->addr == addr || !exact_match_only)
|
||||
return &(*pos);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const Entry *
|
||||
FindNextEntry (const Entry *entry)
|
||||
{
|
||||
if (entry >= &*m_entries.begin() && entry + 1 < &*m_entries.end())
|
||||
return entry + 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Entry *
|
||||
Back()
|
||||
{
|
||||
if (!m_entries.empty())
|
||||
return &m_entries.back();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const Entry *
|
||||
Back() const
|
||||
{
|
||||
if (!m_entries.empty())
|
||||
return &m_entries.back();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
protected:
|
||||
Collection m_entries;
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // liblldb_RangeMap_h_
|
||||
|
|
|
@ -211,6 +211,7 @@ public:
|
|||
void
|
||||
SetByteSize (uint32_t size)
|
||||
{
|
||||
m_calculated_size = size > 0;
|
||||
m_addr_range.SetByteSize(size);
|
||||
}
|
||||
|
||||
|
|
|
@ -1142,7 +1142,14 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
Timer scoped_timer(__PRETTY_FUNCTION__,
|
||||
"ObjectFileMachO::ParseSymtab () module = %s",
|
||||
m_file.GetFilename().AsCString(""));
|
||||
struct symtab_command symtab_load_command;
|
||||
ModuleSP module_sp (GetModule());
|
||||
if (!module_sp)
|
||||
return 0;
|
||||
|
||||
struct symtab_command symtab_load_command = { 0, 0, 0, 0, 0, 0 };
|
||||
struct linkedit_data_command function_starts_load_command = { 0, 0, 0, 0 };
|
||||
typedef AddressDataArray<lldb::addr_t, bool, 100> FunctionStarts;
|
||||
FunctionStarts function_starts;
|
||||
uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
|
||||
uint32_t i;
|
||||
|
||||
|
@ -1152,42 +1159,62 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
{
|
||||
const uint32_t cmd_offset = offset;
|
||||
// Read in the load command and load command size
|
||||
if (m_data.GetU32(&offset, &symtab_load_command, 2) == NULL)
|
||||
struct load_command lc;
|
||||
if (m_data.GetU32(&offset, &lc, 2) == NULL)
|
||||
break;
|
||||
// Watch for the symbol table load command
|
||||
if (symtab_load_command.cmd == LoadCommandSymtab)
|
||||
switch (lc.cmd)
|
||||
{
|
||||
case LoadCommandSymtab:
|
||||
symtab_load_command.cmd = lc.cmd;
|
||||
symtab_load_command.cmdsize = lc.cmdsize;
|
||||
// Read in the rest of the symtab load command
|
||||
if (m_data.GetU32(&offset, &symtab_load_command.symoff, 4)) // fill in symoff, nsyms, stroff, strsize fields
|
||||
{
|
||||
if (m_data.GetU32(&offset, &symtab_load_command.symoff, 4) == 0) // fill in symoff, nsyms, stroff, strsize fields
|
||||
return 0;
|
||||
if (symtab_load_command.symoff == 0)
|
||||
{
|
||||
if (log)
|
||||
GetModule()->LogMessage(log.get(), "LC_SYMTAB.symoff == 0");
|
||||
module_sp->LogMessage(log.get(), "LC_SYMTAB.symoff == 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (symtab_load_command.stroff == 0)
|
||||
{
|
||||
if (log)
|
||||
GetModule()->LogMessage(log.get(), "LC_SYMTAB.stroff == 0");
|
||||
module_sp->LogMessage(log.get(), "LC_SYMTAB.stroff == 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (symtab_load_command.nsyms == 0)
|
||||
{
|
||||
if (log)
|
||||
GetModule()->LogMessage(log.get(), "LC_SYMTAB.nsyms == 0");
|
||||
module_sp->LogMessage(log.get(), "LC_SYMTAB.nsyms == 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (symtab_load_command.strsize == 0)
|
||||
{
|
||||
if (log)
|
||||
GetModule()->LogMessage(log.get(), "LC_SYMTAB.strsize == 0");
|
||||
module_sp->LogMessage(log.get(), "LC_SYMTAB.strsize == 0");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case LoadCommandFunctionStarts:
|
||||
function_starts_load_command.cmd = lc.cmd;
|
||||
function_starts_load_command.cmdsize = lc.cmdsize;
|
||||
if (m_data.GetU32(&offset, &function_starts_load_command.dataoff, 2) == NULL) // fill in symoff, nsyms, stroff, strsize fields
|
||||
bzero (&function_starts_load_command, sizeof(function_starts_load_command));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
offset = cmd_offset + lc.cmdsize;
|
||||
}
|
||||
|
||||
if (symtab_load_command.cmd)
|
||||
{
|
||||
Symtab *symtab = m_symtab_ap.get();
|
||||
SectionList *section_list = GetSectionList();
|
||||
if (section_list == NULL)
|
||||
|
@ -1201,6 +1228,7 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
|
||||
DataExtractor nlist_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize());
|
||||
DataExtractor strtab_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize());
|
||||
DataExtractor function_starts_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize());
|
||||
|
||||
const addr_t nlist_data_byte_size = symtab_load_command.nsyms * nlist_byte_size;
|
||||
const addr_t strtab_data_byte_size = symtab_load_command.strsize;
|
||||
|
@ -1222,6 +1250,13 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
DataBufferSP strtab_data_sp (ReadMemory (process_sp, stroff_addr, strtab_data_byte_size));
|
||||
if (strtab_data_sp)
|
||||
strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize());
|
||||
if (function_starts_load_command.cmd)
|
||||
{
|
||||
const addr_t func_start_addr = linkedit_load_addr + function_starts_load_command.dataoff - linkedit_file_offset;
|
||||
DataBufferSP func_start_data_sp (ReadMemory (process_sp, func_start_addr, function_starts_load_command.datasize));
|
||||
if (func_start_data_sp)
|
||||
function_starts_data.SetData (func_start_data_sp, 0, func_start_data_sp->GetByteSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1232,13 +1267,18 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
strtab_data.SetData (m_data,
|
||||
symtab_load_command.stroff,
|
||||
strtab_data_byte_size);
|
||||
|
||||
if (function_starts_load_command.cmd)
|
||||
{
|
||||
function_starts_data.SetData (m_data,
|
||||
function_starts_load_command.dataoff,
|
||||
function_starts_load_command.datasize);
|
||||
}
|
||||
}
|
||||
|
||||
if (nlist_data.GetByteSize() == 0)
|
||||
{
|
||||
if (log)
|
||||
GetModule()->LogMessage(log.get(), "failed to read nlist data");
|
||||
module_sp->LogMessage(log.get(), "failed to read nlist data");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1246,7 +1286,7 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
if (strtab_data.GetByteSize() == 0)
|
||||
{
|
||||
if (log)
|
||||
GetModule()->LogMessage(log.get(), "failed to read strtab data");
|
||||
module_sp->LogMessage(log.get(), "failed to read strtab data");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1263,6 +1303,24 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
else
|
||||
eh_frame_section_sp = section_list->FindSectionByName (g_section_name_eh_frame);
|
||||
|
||||
|
||||
if (text_section_sp && function_starts_data.GetByteSize())
|
||||
{
|
||||
FunctionStarts::Entry function_start_entry;
|
||||
function_start_entry.data = false;
|
||||
uint32_t function_start_offset = 0;
|
||||
function_start_entry.addr = text_section_sp->GetFileAddress();
|
||||
uint64_t delta;
|
||||
while ((delta = function_starts_data.GetULEB128(&function_start_offset)) > 0)
|
||||
{
|
||||
// Now append the current entry
|
||||
function_start_entry.addr += delta;
|
||||
function_starts.Append(function_start_entry);
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t function_starts_count = function_starts.GetSize();
|
||||
|
||||
uint8_t TEXT_eh_frame_sectID = eh_frame_section_sp.get() ? eh_frame_section_sp->GetID() : NListSectionNoSection;
|
||||
|
||||
uint32_t nlist_data_offset = 0;
|
||||
|
@ -1306,19 +1364,15 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
const char *symbol_name = strtab_data.PeekCStr(nlist.n_strx);
|
||||
if (symbol_name == NULL)
|
||||
{
|
||||
ModuleSP module_sp (GetModule());
|
||||
// No symbol should be NULL, even the symbols with no
|
||||
// string values should have an offset zero which points
|
||||
// to an empty C-string
|
||||
if (module_sp)
|
||||
{
|
||||
Host::SystemLog (Host::eSystemLogError,
|
||||
"error: symbol[%u] has invalid string table offset 0x%x in %s/%s, ignoring symbol\n",
|
||||
nlist_idx,
|
||||
nlist.n_strx,
|
||||
module_sp->GetFileSpec().GetDirectory().GetCString(),
|
||||
module_sp->GetFileSpec().GetFilename().GetCString());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const char *symbol_name_non_abi_mangled = NULL;
|
||||
|
@ -1326,6 +1380,7 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
if (symbol_name[0] == '\0')
|
||||
symbol_name = NULL;
|
||||
SectionSP symbol_section;
|
||||
uint32_t symbol_byte_size = 0;
|
||||
bool add_nlist = true;
|
||||
bool is_debug = ((nlist.n_type & NlistMaskStab) != 0);
|
||||
|
||||
|
@ -1682,6 +1737,7 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
break;
|
||||
|
||||
case NListTypeSection: // N_SECT
|
||||
{
|
||||
symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
|
||||
|
||||
if (symbol_section == NULL)
|
||||
|
@ -1802,6 +1858,7 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1875,8 +1932,29 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (symbol_section != NULL)
|
||||
symbol_value -= symbol_section->GetFileAddress();
|
||||
if (symbol_section)
|
||||
{
|
||||
const addr_t section_file_addr = symbol_section->GetFileAddress();
|
||||
if (symbol_byte_size == 0 && function_starts_count > 0)
|
||||
{
|
||||
FunctionStarts::Entry *func_start_entry = function_starts.FindEntry(nlist.n_value, true);
|
||||
if (func_start_entry)
|
||||
{
|
||||
func_start_entry->data = true;
|
||||
const FunctionStarts::Entry *next_func_start_entry = function_starts.FindNextEntry (func_start_entry);
|
||||
const addr_t section_end_file_addr = section_file_addr + symbol_section->GetByteSize();
|
||||
if (next_func_start_entry)
|
||||
{
|
||||
symbol_byte_size = std::min<lldb::addr_t>(next_func_start_entry->addr - func_start_entry->addr, section_end_file_addr - func_start_entry->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
symbol_byte_size = section_end_file_addr - func_start_entry->addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
symbol_value -= section_file_addr;
|
||||
}
|
||||
|
||||
sym[sym_idx].SetID (nlist_idx);
|
||||
sym[sym_idx].SetType (type);
|
||||
|
@ -1884,6 +1962,9 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
sym[sym_idx].GetAddress().SetOffset (symbol_value);
|
||||
sym[sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc);
|
||||
|
||||
if (symbol_byte_size > 0)
|
||||
sym[sym_idx].SetByteSize(symbol_byte_size);
|
||||
|
||||
++sym_idx;
|
||||
}
|
||||
else
|
||||
|
@ -1924,6 +2005,70 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t synthetic_sym_id = symtab_load_command.nsyms;
|
||||
|
||||
|
||||
if (function_starts_count > 0)
|
||||
{
|
||||
char synthetic_function_symbol[PATH_MAX];
|
||||
uint32_t num_synthetic_function_symbols = 0;
|
||||
for (i=0; i<function_starts_count; ++i)
|
||||
{
|
||||
if (function_starts.GetEntryRef (i).data == false)
|
||||
++num_synthetic_function_symbols;
|
||||
}
|
||||
|
||||
if (num_synthetic_function_symbols > 0)
|
||||
{
|
||||
if (num_syms < sym_idx + num_synthetic_function_symbols)
|
||||
{
|
||||
num_syms = sym_idx + num_synthetic_function_symbols;
|
||||
sym = symtab->Resize (num_syms);
|
||||
}
|
||||
uint32_t synthetic_function_symbol_idx = 0;
|
||||
for (i=0; i<function_starts_count; ++i)
|
||||
{
|
||||
const FunctionStarts::Entry *func_start_entry = function_starts.GetEntryAtIndex (i);
|
||||
if (func_start_entry->data == false)
|
||||
{
|
||||
Address symbol_addr;
|
||||
if (module_sp->ResolveFileAddress (func_start_entry->addr, symbol_addr))
|
||||
{
|
||||
SectionSP symbol_section (symbol_addr.GetSection());
|
||||
uint32_t symbol_byte_size = 0;
|
||||
if (symbol_section)
|
||||
{
|
||||
const addr_t section_file_addr = symbol_section->GetFileAddress();
|
||||
const FunctionStarts::Entry *next_func_start_entry = function_starts.FindNextEntry (func_start_entry);
|
||||
const addr_t section_end_file_addr = section_file_addr + symbol_section->GetByteSize();
|
||||
if (next_func_start_entry)
|
||||
{
|
||||
symbol_byte_size = std::min<lldb::addr_t>(next_func_start_entry->addr - func_start_entry->addr, section_end_file_addr - func_start_entry->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
symbol_byte_size = section_end_file_addr - func_start_entry->addr;
|
||||
}
|
||||
snprintf (synthetic_function_symbol,
|
||||
sizeof(synthetic_function_symbol),
|
||||
"___lldb_unnamed_function%u$$%s",
|
||||
++synthetic_function_symbol_idx,
|
||||
module_sp->GetFileSpec().GetFilename().GetCString());
|
||||
sym[sym_idx].SetID (synthetic_sym_id++);
|
||||
sym[sym_idx].GetMangled().SetDemangledName(synthetic_function_symbol);
|
||||
sym[sym_idx].SetType (eSymbolTypeCode);
|
||||
sym[sym_idx].SetIsSynthetic (true);
|
||||
sym[sym_idx].GetAddress() = symbol_addr;
|
||||
if (symbol_byte_size)
|
||||
sym[sym_idx].SetByteSize (symbol_byte_size);
|
||||
++sym_idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trim our symbols down to just what we ended up with after
|
||||
// removing any symbols.
|
||||
if (sym_idx < num_syms)
|
||||
|
@ -1955,7 +2100,6 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
continue;
|
||||
|
||||
const uint32_t symbol_stub_index_offset = m_mach_sections[sect_idx].reserved1;
|
||||
uint32_t synthetic_stub_sym_id = symtab_load_command.nsyms;
|
||||
for (uint32_t stub_idx = 0; stub_idx < num_symbol_stubs; ++stub_idx)
|
||||
{
|
||||
const uint32_t symbol_stub_index = symbol_stub_index_offset + stub_idx;
|
||||
|
@ -2004,7 +2148,7 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
// Make a synthetic symbol to describe the trampoline stub
|
||||
if (sym_idx >= num_syms)
|
||||
sym = symtab->Resize (++num_syms);
|
||||
sym[sym_idx].SetID (synthetic_stub_sym_id++);
|
||||
sym[sym_idx].SetID (synthetic_sym_id++);
|
||||
sym[sym_idx].GetMangled() = stub_symbol->GetMangled();
|
||||
sym[sym_idx].SetType (eSymbolTypeTrampoline);
|
||||
sym[sym_idx].SetIsSynthetic (true);
|
||||
|
@ -2021,9 +2165,6 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
}
|
||||
return symtab->GetNumSymbols();
|
||||
}
|
||||
}
|
||||
offset = cmd_offset + symtab_load_command.cmdsize;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue