Skip to content

Commit

Permalink
[llvm-objcopy] - Refactor the code. NFC.
Browse files Browse the repository at this point in the history
The idea of the patch is about to move out the code to a new
helper static functions (to reduce the size of 'handleArgs' and to
isolate the parts of it's logic).

Differential revision: https://reviews.llvm.org/D59762

llvm-svn: 356889
  • Loading branch information
George Rimar committed Mar 25, 2019
1 parent 948e37c commit e6963be
Showing 1 changed file with 106 additions and 96 deletions.
202 changes: 106 additions & 96 deletions llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,110 +298,94 @@ static bool isUnneededSymbol(const Symbol &Sym) {
Sym.Type != STT_FILE && Sym.Type != STT_SECTION;
}

// This function handles the high level operations of GNU objcopy including
// handling command line options. It's important to outline certain properties
// we expect to hold of the command line operations. Any operation that "keeps"
// should keep regardless of a remove. Additionally any removal should respect
// any previous removals. Lastly whether or not something is removed shouldn't
// depend a) on the order the options occur in or b) on some opaque priority
// system. The only priority is that keeps/copies overrule removes.
static Error handleArgs(const CopyConfig &Config, Object &Obj,
const Reader &Reader, ElfType OutputElfType) {

if (!Config.SplitDWO.empty())
if (Error E =
splitDWOToFile(Config, Reader, Config.SplitDWO, OutputElfType))
return E;

if (Config.OutputArch) {
Obj.Machine = Config.OutputArch.getValue().EMachine;
Obj.OSABI = Config.OutputArch.getValue().OSABI;
}

static Error updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) {
// TODO: update or remove symbols only if there is an option that affects
// them.
if (Obj.SymbolTable) {
Obj.SymbolTable->updateSymbols([&](Symbol &Sym) {
// Common and undefined symbols don't make sense as local symbols, and can
// even cause crashes if we localize those, so skip them.
if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF &&
((Config.LocalizeHidden &&
(Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) ||
is_contained(Config.SymbolsToLocalize, Sym.Name)))
Sym.Binding = STB_LOCAL;

// Note: these two globalize flags have very similar names but different
// meanings:
//
// --globalize-symbol: promote a symbol to global
// --keep-global-symbol: all symbols except for these should be made local
//
// If --globalize-symbol is specified for a given symbol, it will be
// global in the output file even if it is not included via
// --keep-global-symbol. Because of that, make sure to check
// --globalize-symbol second.
if (!Config.SymbolsToKeepGlobal.empty() &&
!is_contained(Config.SymbolsToKeepGlobal, Sym.Name) &&
Sym.getShndx() != SHN_UNDEF)
Sym.Binding = STB_LOCAL;

if (is_contained(Config.SymbolsToGlobalize, Sym.Name) &&
Sym.getShndx() != SHN_UNDEF)
Sym.Binding = STB_GLOBAL;

if (is_contained(Config.SymbolsToWeaken, Sym.Name) &&
Sym.Binding == STB_GLOBAL)
Sym.Binding = STB_WEAK;

if (Config.Weaken && Sym.Binding == STB_GLOBAL &&
Sym.getShndx() != SHN_UNDEF)
Sym.Binding = STB_WEAK;

const auto I = Config.SymbolsToRename.find(Sym.Name);
if (I != Config.SymbolsToRename.end())
Sym.Name = I->getValue();

if (!Config.SymbolsPrefix.empty() && Sym.Type != STT_SECTION)
Sym.Name = (Config.SymbolsPrefix + Sym.Name).str();
});

// The purpose of this loop is to mark symbols referenced by sections
// (like GroupSection or RelocationSection). This way, we know which
// symbols are still 'needed' and which are not.
if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty()) {
for (auto &Section : Obj.sections())
Section.markSymbols();
}
if (!Obj.SymbolTable)
return Error::success();

Obj.SymbolTable->updateSymbols([&](Symbol &Sym) {
// Common and undefined symbols don't make sense as local symbols, and can
// even cause crashes if we localize those, so skip them.
if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF &&
((Config.LocalizeHidden &&
(Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) ||
is_contained(Config.SymbolsToLocalize, Sym.Name)))
Sym.Binding = STB_LOCAL;

// Note: these two globalize flags have very similar names but different
// meanings:
//
// --globalize-symbol: promote a symbol to global
// --keep-global-symbol: all symbols except for these should be made local
//
// If --globalize-symbol is specified for a given symbol, it will be
// global in the output file even if it is not included via
// --keep-global-symbol. Because of that, make sure to check
// --globalize-symbol second.
if (!Config.SymbolsToKeepGlobal.empty() &&
!is_contained(Config.SymbolsToKeepGlobal, Sym.Name) &&
Sym.getShndx() != SHN_UNDEF)
Sym.Binding = STB_LOCAL;

if (is_contained(Config.SymbolsToGlobalize, Sym.Name) &&
Sym.getShndx() != SHN_UNDEF)
Sym.Binding = STB_GLOBAL;

if (is_contained(Config.SymbolsToWeaken, Sym.Name) &&
Sym.Binding == STB_GLOBAL)
Sym.Binding = STB_WEAK;

if (Config.Weaken && Sym.Binding == STB_GLOBAL &&
Sym.getShndx() != SHN_UNDEF)
Sym.Binding = STB_WEAK;

const auto I = Config.SymbolsToRename.find(Sym.Name);
if (I != Config.SymbolsToRename.end())
Sym.Name = I->getValue();

if (!Config.SymbolsPrefix.empty() && Sym.Type != STT_SECTION)
Sym.Name = (Config.SymbolsPrefix + Sym.Name).str();
});

// The purpose of this loop is to mark symbols referenced by sections
// (like GroupSection or RelocationSection). This way, we know which
// symbols are still 'needed' and which are not.
if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty()) {
for (auto &Section : Obj.sections())
Section.markSymbols();
}

auto RemoveSymbolsPred = [&](const Symbol &Sym) {
if (is_contained(Config.SymbolsToKeep, Sym.Name) ||
(Config.KeepFileSymbols && Sym.Type == STT_FILE))
return false;
auto RemoveSymbolsPred = [&](const Symbol &Sym) {
if (is_contained(Config.SymbolsToKeep, Sym.Name) ||
(Config.KeepFileSymbols && Sym.Type == STT_FILE))
return false;

if ((Config.DiscardMode == DiscardType::All ||
(Config.DiscardMode == DiscardType::Locals &&
StringRef(Sym.Name).startswith(".L"))) &&
Sym.Binding == STB_LOCAL && Sym.getShndx() != SHN_UNDEF &&
Sym.Type != STT_FILE && Sym.Type != STT_SECTION)
return true;
if ((Config.DiscardMode == DiscardType::All ||
(Config.DiscardMode == DiscardType::Locals &&
StringRef(Sym.Name).startswith(".L"))) &&
Sym.Binding == STB_LOCAL && Sym.getShndx() != SHN_UNDEF &&
Sym.Type != STT_FILE && Sym.Type != STT_SECTION)
return true;

if (Config.StripAll || Config.StripAllGNU)
return true;
if (Config.StripAll || Config.StripAllGNU)
return true;

if (is_contained(Config.SymbolsToRemove, Sym.Name))
return true;
if (is_contained(Config.SymbolsToRemove, Sym.Name))
return true;

if ((Config.StripUnneeded ||
is_contained(Config.UnneededSymbolsToRemove, Sym.Name)) &&
isUnneededSymbol(Sym))
return true;
if ((Config.StripUnneeded ||
is_contained(Config.UnneededSymbolsToRemove, Sym.Name)) &&
isUnneededSymbol(Sym))
return true;

return false;
};
if (Error E = Obj.removeSymbols(RemoveSymbolsPred))
return E;
}
return false;
};

return Obj.removeSymbols(RemoveSymbolsPred);
}

static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) {
SectionPred RemovePred = [](const SectionBase &) { return false; };

// Removes:
Expand Down Expand Up @@ -535,7 +519,33 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj,
return &Obj.addSection<DecompressedSection>(*CS);
});

if (Error E = Obj.removeSections(RemovePred))
return Obj.removeSections(RemovePred);
}

// This function handles the high level operations of GNU objcopy including
// handling command line options. It's important to outline certain properties
// we expect to hold of the command line operations. Any operation that "keeps"
// should keep regardless of a remove. Additionally any removal should respect
// any previous removals. Lastly whether or not something is removed shouldn't
// depend a) on the order the options occur in or b) on some opaque priority
// system. The only priority is that keeps/copies overrule removes.
static Error handleArgs(const CopyConfig &Config, Object &Obj,
const Reader &Reader, ElfType OutputElfType) {

if (!Config.SplitDWO.empty())
if (Error E =
splitDWOToFile(Config, Reader, Config.SplitDWO, OutputElfType))
return E;

if (Config.OutputArch) {
Obj.Machine = Config.OutputArch.getValue().EMachine;
Obj.OSABI = Config.OutputArch.getValue().OSABI;
}

if (Error E = updateAndRemoveSymbols(Config, Obj))
return E;

if (Error E = replaceAndRemoveSections(Config, Obj))
return E;

if (!Config.SectionsToRename.empty()) {
Expand Down

0 comments on commit e6963be

Please sign in to comment.