Ejemplo n.º 1
0
/// Interpret the STAB entries to fill the DebugMap.
void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex,
                                                     uint8_t Type,
                                                     uint8_t SectionIndex,
                                                     uint16_t Flags,
                                                     uint64_t Value) {
  if (!(Type & MachO::N_STAB))
    return;

  const char *Name = &MainBinaryStrings.data()[StringIndex];

  // An N_OSO entry represents the start of a new object file description.
  if (Type == MachO::N_OSO) {
    sys::TimeValue Timestamp;
    Timestamp.fromEpochTime(Value);
    return switchToNewDebugMapObject(Name, Timestamp);
  }

  // If the last N_OSO object file wasn't found,
  // CurrentDebugMapObject will be null. Do not update anything
  // until we find the next valid N_OSO entry.
  if (!CurrentDebugMapObject)
    return;

  uint32_t Size = 0;
  switch (Type) {
  case MachO::N_GSYM:
    // This is a global variable. We need to query the main binary
    // symbol table to find its address as it might not be in the
    // debug map (for common symbols).
    Value = getMainBinarySymbolAddress(Name);
    break;
  case MachO::N_FUN:
    // Functions are scopes in STABS. They have an end marker that
    // contains the function size.
    if (Name[0] == '\0') {
      Size = Value;
      Value = CurrentFunctionAddress;
      Name = CurrentFunctionName;
      break;
    } else {
      CurrentFunctionName = Name;
      CurrentFunctionAddress = Value;
      return;
    }
  case MachO::N_STSYM:
    break;
  default:
    return;
  }

  auto ObjectSymIt = CurrentObjectAddresses.find(Name);
  if (ObjectSymIt == CurrentObjectAddresses.end())
    return Warning("could not find object file symbol for symbol " +
                   Twine(Name));
  if (!CurrentDebugMapObject->addSymbol(Name, ObjectSymIt->getValue(), Value,
                                        Size))
    return Warning(Twine("failed to insert symbol '") + Name +
                   "' in the debug map.");
}
/// Load the current object file symbols into CurrentObjectAddresses.
void MachODebugMapParser::loadCurrentObjectFileSymbols(
    const object::MachOObjectFile &Obj) {
  CurrentObjectAddresses.clear();

  for (auto Sym : Obj.symbols()) {
    StringRef Name;
    uint64_t Addr = UnknownAddressOrSize;
    SymbolRef::Type Type;
    StringRef SecName;

    // Undefined symbols won't have an address, but we still want
    // them, because they might be referenced in the debug information.
    Sym.getAddress(Addr);

    object::section_iterator Section = Obj.section_end();
    if (!Sym.getSection(Section) && Section != Obj.section_end())
      Section->getName(SecName);

    if (Sym.getName(Name) || Name.empty() ||
        Sym.getType(Type) || Type == SymbolRef::ST_Other)
      continue;

    CurrentObjectAddresses.insert(std::make_pair(Name, std::make_pair(Addr, SecName)));
    uint32_t Flags;

    Flags = Sym.getFlags();
    uint64_t Value;
    // FIXME: We put every symbol in the debug map, because of the
    // behavior expected from lookupObjectAddress.
      Value = getMainBinarySymbolAddress(Name);

    // Symbols with no known address on either side are of absolutely
    // no use.
    if (Addr != UnknownAddressOrSize || Value != UnknownAddressOrSize)
      CurrentDebugMapObject->addSymbol(Name, Addr, Value, 0, SecName, true);
  }
}