[ifs] Add --strip-size flag

st_size may not be of importance to the abi if you are not using
copy relocations. This is helpful when you want to check the abi
of a shared object both when instrumented and not because asan
will increase the size of objects to include the redzone.

Differential revision: https://reviews.llvm.org/D124792
This commit is contained in:
Alex Brachet 2022-05-14 18:50:20 +00:00
parent 60e5fd00cd
commit a74d9e74e5
7 changed files with 49 additions and 12 deletions

View File

@ -194,6 +194,13 @@ OPTIONS
When this flag is set, llvm-ifs will only write the output file if it does not
already exist or the content will be different from the existing file.
.. option:: --strip-size
When this flag is set, llvm-ifs will remove the size field from the output ifs
file. This is useful for shared objects that only intend to be linked against
position independent code which doesn't need copy relocations, or where the size
of an object is not a useful part of the abi to track.
EXIT STATUS
-----------

View File

@ -53,7 +53,7 @@ struct IFSSymbol {
IFSSymbol() = default;
explicit IFSSymbol(std::string SymbolName) : Name(std::move(SymbolName)) {}
std::string Name;
uint64_t Size;
Optional<uint64_t> Size;
IFSSymbolType Type;
bool Undefined;
bool Weak;

View File

@ -217,7 +217,8 @@ public:
// time as long as it is not SHN_UNDEF. Set shndx to 1, which
// points to ".dynsym".
uint16_t Shndx = Sym.Undefined ? SHN_UNDEF : 1;
DynSym.Content.add(DynStr.Content.getOffset(Sym.Name), Sym.Size, Bind,
uint64_t Size = Sym.Size ? *Sym.Size : 0;
DynSym.Content.add(DynStr.Content.getOffset(Sym.Name), Size, Bind,
convertIFSSymbolTypeToELF(Sym.Type), 0, Shndx);
}
DynSym.Size = DynSym.Content.getSize();

View File

@ -118,11 +118,12 @@ template <> struct MappingTraits<IFSSymbol> {
IO.mapRequired("Type", Symbol.Type);
// The need for symbol size depends on the symbol type.
if (Symbol.Type == IFSSymbolType::NoType) {
IO.mapOptional("Size", Symbol.Size, (uint64_t)0);
} else if (Symbol.Type == IFSSymbolType::Func) {
Symbol.Size = 0;
} else {
IO.mapRequired("Size", Symbol.Size);
// Size is None, so we are reading it in, or it is non 0 so we
// should emit it.
if (!Symbol.Size || *Symbol.Size)
IO.mapOptional("Size", Symbol.Size);
} else if (Symbol.Type != IFSSymbolType::Func) {
IO.mapOptional("Size", Symbol.Size);
}
IO.mapOptional("Undefined", Symbol.Undefined, false);
IO.mapOptional("Weak", Symbol.Weak, false);

View File

@ -0,0 +1,20 @@
# RUN: llvm-ifs %s --output-ifs - --strip-size | FileCheck %s
# CHECK: Symbols:
# CHECK-NEXT: - { Name: sym, Type: Object }
# CHECK-NEXT: ...
## Check that the size when emitting to elf defaults to 1.
# RUN: llvm-ifs %s --output-elf - --strip-size | llvm-ifs - --output-ifs - | \
# RUN: FileCheck %s --check-prefix=ELF
# ELF: Symbols:
# ELF-NEXT: - { Name: sym, Type: Object, Size: 0 }
# ELF-NEXT: ...
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64
Symbols:
- { Name: sym, Type: Object, Size: 2 }
...

View File

@ -107,6 +107,10 @@ cl::opt<bool>
cl::opt<bool> StripNeededLibs("strip-needed",
cl::desc("Strip needed libs from output"),
cl::cat(IfsCategory));
cl::opt<bool> StripSize("strip-size",
cl::desc("Remove object size from the output"),
cl::cat(IfsCategory));
cl::list<std::string>
ExcludeSyms("exclude",
cl::desc("Remove symbols which match the pattern. Can be "
@ -432,6 +436,10 @@ int main(int argc, char *argv[]) {
if (Error E = filterIFSSyms(Stub, StripUndefined, ExcludeSyms))
fatalError(std::move(E));
if (StripSize)
for (IFSSymbol &Sym : Stub.Symbols)
Sym.Size.reset();
if (OutputELFFilePath.getNumOccurrences() == 0 &&
OutputIFSFilePath.getNumOccurrences() == 0 &&
OutputTBDFilePath.getNumOccurrences() == 0) {

View File

@ -82,7 +82,7 @@ TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) {
auto Iterator = Stub->Symbols.begin();
IFSSymbol const &SymBar = *Iterator++;
EXPECT_STREQ(SymBar.Name.c_str(), "bar");
EXPECT_EQ(SymBar.Size, 42u);
EXPECT_EQ(*SymBar.Size, 42u);
EXPECT_EQ(SymBar.Type, IFSSymbolType::Object);
EXPECT_FALSE(SymBar.Undefined);
EXPECT_FALSE(SymBar.Weak);
@ -90,7 +90,7 @@ TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) {
IFSSymbol const &SymBaz = *Iterator++;
EXPECT_STREQ(SymBaz.Name.c_str(), "baz");
EXPECT_EQ(SymBaz.Size, 3u);
EXPECT_EQ(*SymBaz.Size, 3u);
EXPECT_EQ(SymBaz.Type, IFSSymbolType::TLS);
EXPECT_FALSE(SymBaz.Undefined);
EXPECT_FALSE(SymBaz.Weak);
@ -98,7 +98,7 @@ TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) {
IFSSymbol const &SymFoo = *Iterator++;
EXPECT_STREQ(SymFoo.Name.c_str(), "foo");
EXPECT_EQ(SymFoo.Size, 0u);
EXPECT_FALSE(SymFoo.Size.hasValue());
EXPECT_EQ(SymFoo.Type, IFSSymbolType::Func);
EXPECT_FALSE(SymFoo.Undefined);
EXPECT_FALSE(SymFoo.Weak);
@ -107,7 +107,7 @@ TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) {
IFSSymbol const &SymNor = *Iterator++;
EXPECT_STREQ(SymNor.Name.c_str(), "nor");
EXPECT_EQ(SymNor.Size, 0u);
EXPECT_FALSE(SymNor.Size.hasValue());
EXPECT_EQ(SymNor.Type, IFSSymbolType::NoType);
EXPECT_TRUE(SymNor.Undefined);
EXPECT_FALSE(SymNor.Weak);
@ -115,7 +115,7 @@ TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) {
IFSSymbol const &SymNot = *Iterator++;
EXPECT_STREQ(SymNot.Name.c_str(), "not");
EXPECT_EQ(SymNot.Size, 111u);
EXPECT_EQ(*SymNot.Size, 111u);
EXPECT_EQ(SymNot.Type, IFSSymbolType::Unknown);
EXPECT_TRUE(SymNot.Undefined);
EXPECT_TRUE(SymNot.Weak);