Skip to content

Commit

Permalink
[ifs] Add --strip-size flag
Browse files Browse the repository at this point in the history
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
  • Loading branch information
abrachet committed May 14, 2022
1 parent 60e5fd0 commit a74d9e7
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 12 deletions.
7 changes: 7 additions & 0 deletions llvm/docs/CommandGuide/llvm-ifs.rst
Expand Up @@ -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
-----------

Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/InterfaceStub/IFSStub.h
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/InterfaceStub/ELFObjHandler.cpp
Expand Up @@ -217,7 +217,8 @@ template <class ELFT> class ELFStubBuilder {
// 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();
Expand Down
11 changes: 6 additions & 5 deletions llvm/lib/InterfaceStub/IFSHandler.cpp
Expand Up @@ -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);
Expand Down
20 changes: 20 additions & 0 deletions llvm/test/tools/llvm-ifs/strip-size.test
@@ -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 }
...
8 changes: 8 additions & 0 deletions llvm/tools/llvm-ifs/llvm-ifs.cpp
Expand Up @@ -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 "
Expand Down Expand Up @@ -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) {
Expand Down
10 changes: 5 additions & 5 deletions llvm/unittests/InterfaceStub/ELFYAMLTest.cpp
Expand Up @@ -82,23 +82,23 @@ 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);
EXPECT_FALSE(SymBar.Warning.hasValue());

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);
EXPECT_FALSE(SymBaz.Warning.hasValue());

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);
Expand All @@ -107,15 +107,15 @@ 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);
EXPECT_FALSE(SymNor.Warning.hasValue());

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);
Expand Down

0 comments on commit a74d9e7

Please sign in to comment.