예제 #1
0
bool SymbolTable::addByName(const Atom &newAtom) {
  StringRef name = newAtom.name();
  assert(!name.empty());
  const Atom *existing = findByName(name);
  if (existing == nullptr) {
    // Name is not in symbol table yet, add it associate with this atom.
    _nameTable[name] = &newAtom;
    return true;
  }

  // Do nothing if the same object is added more than once.
  if (existing == &newAtom)
    return false;

  // Name is already in symbol table and associated with another atom.
  bool useNew = true;
  switch (collide(existing->definition(), newAtom.definition())) {
  case NCR_First:
    useNew = false;
    break;
  case NCR_Second:
    useNew = true;
    break;
  case NCR_DupDef:
    assert(existing->definition() == Atom::definitionRegular);
    assert(newAtom.definition() == Atom::definitionRegular);
    switch (mergeSelect(((DefinedAtom*)existing)->merge(),
                        ((DefinedAtom*)&newAtom)->merge())) {
    case MCR_First:
      useNew = false;
      break;
    case MCR_Second:
      useNew = true;
      break;
    case MCR_Largest: {
      uint64_t existingSize = sectionSize((DefinedAtom*)existing);
      uint64_t newSize = sectionSize((DefinedAtom*)&newAtom);
      useNew = (newSize >= existingSize);
      break;
    }
    case MCR_SameSize: {
      uint64_t existingSize = sectionSize((DefinedAtom*)existing);
      uint64_t newSize = sectionSize((DefinedAtom*)&newAtom);
      if (existingSize == newSize) {
        useNew = true;
        break;
      }
      llvm::errs() << "Size mismatch: "
                   << existing->name() << " (" << existingSize << ") "
                   << newAtom.name() << " (" << newSize << ")\n";
      // fallthrough
    }
    case MCR_Error:
      if (!_context.getAllowDuplicates()) {
        llvm::errs() << "Duplicate symbols: "
                     << existing->name()
                     << ":"
                     << existing->file().path()
                     << " and "
                     << newAtom.name()
                     << ":"
                     << newAtom.file().path()
                     << "\n";
        llvm::report_fatal_error("duplicate symbol error");
      }
      useNew = false;
      break;
    }
    break;
  case NCR_DupUndef: {
    const UndefinedAtom* existingUndef = cast<UndefinedAtom>(existing);
    const UndefinedAtom* newUndef = cast<UndefinedAtom>(&newAtom);

    bool sameCanBeNull = (existingUndef->canBeNull() == newUndef->canBeNull());
    if (!sameCanBeNull &&
        _context.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
      llvm::errs() << "lld warning: undefined symbol "
                   << existingUndef->name()
                   << " has different weakness in "
                   << existingUndef->file().path()
                   << " and in " << newUndef->file().path() << "\n";
    }

    const UndefinedAtom *existingFallback = existingUndef->fallback();
    const UndefinedAtom *newFallback = newUndef->fallback();
    bool hasDifferentFallback =
        (existingFallback && newFallback &&
         existingFallback->name() != newFallback->name());
    if (hasDifferentFallback) {
      llvm::errs() << "lld warning: undefined symbol "
                   << existingUndef->name() << " has different fallback: "
                   << existingFallback->name() << " in "
                   << existingUndef->file().path() << " and "
                   << newFallback->name() << " in "
                   << newUndef->file().path() << "\n";
    }

    bool hasNewFallback = newUndef->fallback();
    if (sameCanBeNull)
      useNew = hasNewFallback;
    else
      useNew = (newUndef->canBeNull() < existingUndef->canBeNull());
    break;
  }
  case NCR_DupShLib: {
    const SharedLibraryAtom *curShLib = cast<SharedLibraryAtom>(existing);
    const SharedLibraryAtom *newShLib = cast<SharedLibraryAtom>(&newAtom);
    bool sameNullness =
        (curShLib->canBeNullAtRuntime() == newShLib->canBeNullAtRuntime());
    bool sameName = curShLib->loadName().equals(newShLib->loadName());
    if (sameName && !sameNullness &&
        _context.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
      // FIXME: need diagonstics interface for writing warning messages
      llvm::errs() << "lld warning: shared library symbol "
                   << curShLib->name() << " has different weakness in "
                   << curShLib->file().path() << " and in "
                   << newShLib->file().path();
    }
    if (!sameName && _context.warnIfCoalesableAtomsHaveDifferentLoadName()) {
      // FIXME: need diagonstics interface for writing warning messages
      llvm::errs() << "lld warning: shared library symbol "
                   << curShLib->name() << " has different load path in "
                   << curShLib->file().path() << " and in "
                   << newShLib->file().path();
    }
    useNew = false;
    break;
  }
  case NCR_Error:
    llvm::errs() << "SymbolTable: error while merging " << name << "\n";
    llvm::report_fatal_error("duplicate symbol error");
    break;
  }

  if (useNew) {
    // Update name table to use new atom.
    _nameTable[name] = &newAtom;
    // Add existing atom to replacement table.
    _replacedAtoms[existing] = &newAtom;
  } else {
    // New atom is not being used.  Add it to replacement table.
    _replacedAtoms[&newAtom] = existing;
  }
  return false;
}
예제 #2
0
void SymbolTable::addByName(const Atom & newAtom) {
  StringRef name = newAtom.name();
  const Atom *existing = this->findByName(name);
  if (existing == nullptr) {
    // Name is not in symbol table yet, add it associate with this atom.
    _nameTable[name] = &newAtom;
  }
  else {
    // Name is already in symbol table and associated with another atom.
    bool useNew = true;
    switch (collide(existing->definition(), newAtom.definition())) {
      case NCR_First:
        useNew = false;
        break;
      case NCR_Second:
        useNew = true;
        break;
      case NCR_DupDef:
        assert(existing->definition() == Atom::definitionRegular);
        assert(newAtom.definition() == Atom::definitionRegular);
        switch ( mergeSelect(((DefinedAtom*)existing)->merge(),
                            ((DefinedAtom*)(&newAtom))->merge()) ) {
          case MCR_First:
            useNew = false;
            break;
          case MCR_Second:
            useNew = true;
            break;
          case MCR_Largest:
            useNew = true;
            break;
          case MCR_Error:
            llvm::errs() << "Duplicate symbols: "
                         << existing->name()
                         << ":"
                         << existing->file().path()
                         << " and "
                         << newAtom.name()
                         << ":"
                         << newAtom.file().path()
                         << "\n";
            llvm::report_fatal_error("duplicate symbol error");
            break;
        }
        break;
      case NCR_DupUndef: {
          const UndefinedAtom* existingUndef =
            dyn_cast<UndefinedAtom>(existing);
          const UndefinedAtom* newUndef =
            dyn_cast<UndefinedAtom>(&newAtom);
          assert(existingUndef != nullptr);
          assert(newUndef != nullptr);
          if ( existingUndef->canBeNull() == newUndef->canBeNull() ) {
            useNew = false;
          }
          else {
            if ( _options.warnIfCoalesableAtomsHaveDifferentCanBeNull() ) {
              // FIXME: need diagonstics interface for writing warning messages
              llvm::errs() << "lld warning: undefined symbol "
                           << existingUndef->name()
                           << " has different weakness in "
                           << existingUndef->file().path()
                           << " and in "
                           << newUndef->file().path();
            }
            useNew = (newUndef->canBeNull() < existingUndef->canBeNull());
          }
        }
        break;
      case NCR_DupShLib: {
          const SharedLibraryAtom* curShLib =
            dyn_cast<SharedLibraryAtom>(existing);
          const SharedLibraryAtom* newShLib =
            dyn_cast<SharedLibraryAtom>(&newAtom);
          assert(curShLib != nullptr);
          assert(newShLib != nullptr);
          bool sameNullness = (curShLib->canBeNullAtRuntime()
                                          == newShLib->canBeNullAtRuntime());
          bool sameName = curShLib->loadName().equals(newShLib->loadName());
          if ( !sameName ) {
            useNew = false;
            if ( _options.warnIfCoalesableAtomsHaveDifferentLoadName() ) {
              // FIXME: need diagonstics interface for writing warning messages
              llvm::errs() << "lld warning: shared library symbol "
                           << curShLib->name()
                           << " has different load path in "
                           << curShLib->file().path()
                           << " and in "
                           << newShLib->file().path();
            }
          }
          else if ( ! sameNullness ) {
            useNew = false;
            if ( _options.warnIfCoalesableAtomsHaveDifferentCanBeNull() ) {
              // FIXME: need diagonstics interface for writing warning messages
              llvm::errs() << "lld warning: shared library symbol "
                           << curShLib->name()
                           << " has different weakness in "
                           << curShLib->file().path()
                           << " and in "
                           << newShLib->file().path();
            }
          }
          else {
            // Both shlib atoms are identical and can be coalesced.
            useNew = false;
          }
        }
        break;
      default:
        llvm::report_fatal_error("SymbolTable::addByName(): unhandled switch clause");
    }
    if ( useNew ) {
      // Update name table to use new atom.
      _nameTable[name] = &newAtom;
      // Add existing atom to replacement table.
      _replacedAtoms[existing] = &newAtom;
    }
    else {
      // New atom is not being used.  Add it to replacement table.
      _replacedAtoms[&newAtom] = existing;
    }
  }
}
예제 #3
0
bool SymbolTable::addByName(const Atom &newAtom) {
  StringRef name = newAtom.name();
  assert(!name.empty());
  const Atom *existing = findByName(name);
  if (existing == nullptr) {
    // Name is not in symbol table yet, add it associate with this atom.
    _nameTable[name] = &newAtom;
    return true;
  }

  // Do nothing if the same object is added more than once.
  if (existing == &newAtom)
    return false;

  // Name is already in symbol table and associated with another atom.
  bool useNew = true;
  switch (collide(existing->definition(), newAtom.definition())) {
  case NCR_First:
    useNew = false;
    break;
  case NCR_Second:
    useNew = true;
    break;
  case NCR_DupDef: {
    const auto *existingDef = cast<DefinedAtom>(existing);
    const auto *newDef = cast<DefinedAtom>(&newAtom);
    switch (mergeSelect(existingDef->merge(), newDef->merge())) {
    case MCR_First:
      useNew = false;
      break;
    case MCR_Second:
      useNew = true;
      break;
    case MCR_Largest: {
      uint64_t existingSize = existingDef->sectionSize();
      uint64_t newSize = newDef->sectionSize();
      useNew = (newSize >= existingSize);
      break;
    }
    case MCR_SameSize: {
      uint64_t existingSize = existingDef->sectionSize();
      uint64_t newSize = newDef->sectionSize();
      if (existingSize == newSize) {
        useNew = true;
        break;
      }
      llvm::errs() << "Size mismatch: "
                   << existing->name() << " (" << existingSize << ") "
                   << newAtom.name() << " (" << newSize << ")\n";
      LLVM_FALLTHROUGH;
    }
    case MCR_Error:
      llvm::errs() << "Duplicate symbols: "
                   << existing->name()
                   << ":"
                   << existing->file().path()
                   << " and "
                   << newAtom.name()
                   << ":"
                   << newAtom.file().path()
                   << "\n";
      llvm::report_fatal_error("duplicate symbol error");
      break;
    }
    break;
  }
  case NCR_DupUndef: {
    const UndefinedAtom* existingUndef = cast<UndefinedAtom>(existing);
    const UndefinedAtom* newUndef = cast<UndefinedAtom>(&newAtom);

    bool sameCanBeNull = (existingUndef->canBeNull() == newUndef->canBeNull());
    if (sameCanBeNull)
      useNew = false;
    else
      useNew = (newUndef->canBeNull() < existingUndef->canBeNull());
    break;
  }
  case NCR_DupShLib: {
    useNew = false;
    break;
  }
  case NCR_Error:
    llvm::errs() << "SymbolTable: error while merging " << name << "\n";
    llvm::report_fatal_error("duplicate symbol error");
    break;
  }

  if (useNew) {
    // Update name table to use new atom.
    _nameTable[name] = &newAtom;
    // Add existing atom to replacement table.
    _replacedAtoms[existing] = &newAtom;
  } else {
    // New atom is not being used.  Add it to replacement table.
    _replacedAtoms[&newAtom] = existing;
  }
  return false;
}