[ELF/AArch64] Fix TLS initial executable relocation

This patch fixes the TLS initial executable for AArch64.  Current
implementation have two issues: 1. does not generate dynamic
R_AARCH64_TLS_TPREL64 relocation for the external module symbols,
and 2. does not export the TLS initial executable symbol in dynamic
symbol table.

The fix follows the MIPS strategy to add a arch-specific GOTSection
class to keep track of TLS symbols required to be place in dynamic
symbol table. It also overrides the buildDynamicSymbolTable for
ExecutableWrite class to add the symbols.

It also adds some refactoring on AArch64RelocationPass.cpp based on ARM
backend.

llvm-svn: 238981
This commit is contained in:
Adhemerval Zanella 2015-06-03 21:44:03 +00:00
parent 8c52a9b0f6
commit 9f0c63bfdf
11 changed files with 418 additions and 36 deletions

View File

@ -0,0 +1,50 @@
//===- lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.cpp -------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "AArch64LinkingContext.h"
#include "AArch64ExecutableWriter.h"
#include "AArch64TargetHandler.h"
#include "AArch64SectionChunks.h"
namespace lld {
namespace elf {
AArch64ExecutableWriter::AArch64ExecutableWriter(AArch64LinkingContext &ctx,
AArch64TargetLayout &layout)
: ExecutableWriter(ctx, layout), _targetLayout(layout) {}
void AArch64ExecutableWriter::createImplicitFiles(
std::vector<std::unique_ptr<File>> &result) {
ExecutableWriter::createImplicitFiles(result);
auto gotFile = llvm::make_unique<SimpleFile>("GOTFile");
gotFile->addAtom(*new (gotFile->allocator()) GlobalOffsetTableAtom(*gotFile));
if (this->_ctx.isDynamic())
gotFile->addAtom(*new (gotFile->allocator()) DynamicAtom(*gotFile));
result.push_back(std::move(gotFile));
}
void AArch64ExecutableWriter::buildDynamicSymbolTable(const File &file) {
for (auto sec : this->_layout.sections()) {
if (auto section = dyn_cast<AtomSection<ELF64LE>>(sec)) {
for (const auto &atom : section->atoms()) {
if (_targetLayout.getGOTSection().hasGlobalGOTEntry(atom->_atom)) {
this->_dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
atom->_virtualAddr, atom);
continue;
}
}
}
}
ExecutableWriter<ELF64LE>::buildDynamicSymbolTable(file);
}
} // namespace elf
} // namespace lld

View File

@ -9,36 +9,29 @@
#ifndef AARCH64_EXECUTABLE_WRITER_H
#define AARCH64_EXECUTABLE_WRITER_H
#include "AArch64LinkingContext.h"
#include "ExecutableWriter.h"
namespace lld {
namespace elf {
class AArch64TargetLayout;
class AArch64LinkingContext;
class AArch64ExecutableWriter : public ExecutableWriter<ELF64LE> {
public:
AArch64ExecutableWriter(AArch64LinkingContext &ctx,
TargetLayout<ELF64LE> &layout);
AArch64TargetLayout &layout);
protected:
// Add any runtime files and their atoms to the output
void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
void buildDynamicSymbolTable(const File &file) override;
private:
AArch64TargetLayout &_targetLayout;
};
AArch64ExecutableWriter::AArch64ExecutableWriter(AArch64LinkingContext &ctx,
TargetLayout<ELF64LE> &layout)
: ExecutableWriter(ctx, layout) {}
void AArch64ExecutableWriter::createImplicitFiles(
std::vector<std::unique_ptr<File>> &result) {
ExecutableWriter::createImplicitFiles(result);
auto gotFile = llvm::make_unique<SimpleFile>("GOTFile");
gotFile->addAtom(*new (gotFile->allocator()) GlobalOffsetTableAtom(*gotFile));
if (this->_ctx.isDynamic())
gotFile->addAtom(*new (gotFile->allocator()) DynamicAtom(*gotFile));
result.push_back(std::move(gotFile));
}
} // namespace elf
} // namespace lld

View File

@ -433,6 +433,7 @@ std::error_code AArch64TargetRelocationHandler::applyRelocation(
case R_AARCH64_IRELATIVE:
case R_AARCH64_JUMP_SLOT:
case R_AARCH64_GLOB_DAT:
case R_AARCH64_TLS_TPREL64:
break;
case R_AARCH64_ADR_PREL_PG_HI21:
return relocR_AARCH64_ADR_PREL_PG_HI21(loc, reloc, target, addend);

View File

@ -56,11 +56,20 @@ namespace {
/// \brief Atoms that are used by AArch64 dynamic linking
class AArch64GOTAtom : public GOTAtom {
public:
AArch64GOTAtom(const File &f, StringRef secName) : GOTAtom(f, secName) {}
AArch64GOTAtom(const File &f) : GOTAtom(f, ".got") {}
ArrayRef<uint8_t> rawContent() const override {
return ArrayRef<uint8_t>(AArch64GotAtomContent, 8);
}
protected:
// Constructor for AArch64GOTAtom
AArch64GOTAtom(const File &f, StringRef secName) : GOTAtom(f, secName) {}
};
class AArch64GOTPLTAtom : public AArch64GOTAtom {
public:
AArch64GOTPLTAtom(const File &f) : AArch64GOTAtom(f, ".got.plt") {}
};
class AArch64PLT0Atom : public PLT0Atom {
@ -73,7 +82,7 @@ public:
class AArch64PLTAtom : public PLTAtom {
public:
AArch64PLTAtom(const File &f, StringRef secName) : PLTAtom(f, secName) {}
AArch64PLTAtom(const File &f) : PLTAtom(f, ".plt") {}
ArrayRef<uint8_t> rawContent() const override {
return ArrayRef<uint8_t>(AArch64PltAtomContent, 16);
@ -138,9 +147,11 @@ template <class Derived> class AArch64RelocationPass : public Pass {
break;
case R_AARCH64_ADR_GOT_PAGE:
case R_AARCH64_LD64_GOT_LO12_NC:
static_cast<Derived *>(this)->handleGOT(ref);
break;
case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
static_cast<Derived *>(this)->handleGOT(ref);
static_cast<Derived *>(this)->handleGOTTPREL(ref);
break;
}
}
@ -153,9 +164,9 @@ protected:
auto plt = _pltMap.find(da);
if (plt != _pltMap.end())
return plt->second;
auto ga = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
auto ga = new (_file._alloc) AArch64GOTPLTAtom(_file);
ga->addReferenceELF_AArch64(R_AARCH64_IRELATIVE, 0, da, 0);
auto pa = new (_file._alloc) AArch64PLTAtom(_file, ".plt");
auto pa = new (_file._alloc) AArch64PLTAtom(_file);
pa->addReferenceELF_AArch64(R_AARCH64_PREL32, 2, ga, -4);
#ifndef NDEBUG
ga->_name = "__got_ifunc_";
@ -182,11 +193,11 @@ protected:
}
/// \brief Create a GOT entry for the TP offset of a TLS atom.
const GOTAtom *getGOTTPOFF(const Atom *atom) {
const GOTAtom *getGOTTPREL(const Atom *atom) {
auto got = _gotMap.find(atom);
if (got == _gotMap.end()) {
auto g = new (_file._alloc) AArch64GOTAtom(_file, ".got");
g->addReferenceELF_AArch64(R_AARCH64_GOTREL64, 0, atom, 0);
auto g = new (_file._alloc) AArch64GOTAtom(_file);
g->addReferenceELF_AArch64(R_AARCH64_TLS_TPREL64, 0, atom, 0);
#ifndef NDEBUG
g->_name = "__got_tls_";
g->_name += atom->name();
@ -198,17 +209,19 @@ protected:
return got->second;
}
/// \brief Create a TPOFF64 GOT entry and change the relocation to a PC32 to
/// \brief Create a GOT TPREL entry and change the relocation to a PC32 to
/// the GOT.
void handleGOTTPOFF(const Reference &ref) {
const_cast<Reference &>(ref).setTarget(getGOTTPOFF(ref.target()));
const_cast<Reference &>(ref).setKindValue(R_AARCH64_PREL32);
std::error_code handleGOTTPREL(const Reference &ref) {
if (isa<DefinedAtom>(ref.target())) {
const_cast<Reference &>(ref).setTarget(getGOTTPREL(ref.target()));
}
return std::error_code();
}
/// \brief Create a GOT entry containing 0.
const GOTAtom *getNullGOT() {
if (!_null) {
_null = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
_null = new (_file._alloc) AArch64GOTPLTAtom(_file);
#ifndef NDEBUG
_null->_name = "__got_null";
#endif
@ -219,7 +232,7 @@ protected:
const GOTAtom *getGOT(const DefinedAtom *da) {
auto got = _gotMap.find(da);
if (got == _gotMap.end()) {
auto g = new (_file._alloc) AArch64GOTAtom(_file, ".got");
auto g = new (_file._alloc) AArch64GOTAtom(_file);
g->addReferenceELF_AArch64(R_AARCH64_ABS64, 0, da, 0);
#ifndef NDEBUG
g->_name = "__got_";
@ -386,8 +399,8 @@ public:
// Fill in the null entry.
getNullGOT();
_plt0 = new (_file._alloc) AArch64PLT0Atom(_file);
_got0 = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
_got1 = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
_got0 = new (_file._alloc) AArch64GOTPLTAtom(_file);
_got1 = new (_file._alloc) AArch64GOTPLTAtom(_file);
_plt0->addReferenceELF_AArch64(R_AARCH64_ADR_GOT_PAGE, 4, _got0, 0);
_plt0->addReferenceELF_AArch64(R_AARCH64_LD64_GOT_LO12_NC, 8, _got1, 0);
_plt0->addReferenceELF_AArch64(ADD_AARCH64_GOTRELINDEX, 12, _got1, 0);
@ -403,9 +416,9 @@ public:
auto plt = _pltMap.find(a);
if (plt != _pltMap.end())
return plt->second;
auto ga = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
auto ga = new (_file._alloc) AArch64GOTPLTAtom(_file);
ga->addReferenceELF_AArch64(R_AARCH64_JUMP_SLOT, 0, a, 0);
auto pa = new (_file._alloc) AArch64PLTAtom(_file, ".plt");
auto pa = new (_file._alloc) AArch64PLTAtom(_file);
pa->addReferenceELF_AArch64(R_AARCH64_ADR_GOT_PAGE, 0, ga, 0);
pa->addReferenceELF_AArch64(R_AARCH64_LD64_GOT_LO12_NC, 4, ga, 0);
pa->addReferenceELF_AArch64(ADD_AARCH64_GOTRELINDEX, 8, ga, 0);
@ -472,7 +485,7 @@ public:
const GOTAtom *getSharedGOT(const SharedLibraryAtom *sla) {
auto got = _gotMap.find(sla);
if (got == _gotMap.end()) {
auto g = new (_file._alloc) AArch64GOTAtom(_file, ".got");
auto g = new (_file._alloc) AArch64GOTAtom(_file);
g->addReferenceELF_AArch64(R_AARCH64_GLOB_DAT, 0, sla, 0);
#ifndef NDEBUG
g->_name = "__got_";

View File

@ -0,0 +1,38 @@
//===- lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.cpp --------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "AArch64SectionChunks.h"
#include "TargetLayout.h"
namespace lld {
namespace elf {
AArch64GOTSection::AArch64GOTSection(const ELFLinkingContext &ctx)
: AtomSection<ELF64LE>(ctx, ".got", DefinedAtom::typeGOT, DefinedAtom::permRW_,
TargetLayout<ELF64LE>::ORDER_GOT)
{
this->_alignment = 8;
}
const AtomLayout *AArch64GOTSection::appendAtom(const Atom *atom) {
const DefinedAtom *da = dyn_cast<DefinedAtom>(atom);
for (const auto &r : *da) {
if (r->kindNamespace() != Reference::KindNamespace::ELF)
continue;
assert(r->kindArch() == Reference::KindArch::AArch64);
if (r->kindValue() == R_AARCH64_TLS_TPREL64)
_tlsMap[r->target()] = _tlsMap.size();
}
return AtomSection<ELF64LE>::appendAtom(atom);
}
} // elf
} // lld

View File

@ -0,0 +1,36 @@
//===- lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.h ----------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_ELF_AARCH64_AARCH64_SECTION_CHUNKS_H
#define LLD_READER_WRITER_ELF_AARCH64_AARCH64_SECTION_CHUNKS_H
#include "TargetLayout.h"
namespace lld {
namespace elf {
class AArch64GOTSection : public AtomSection<ELF64LE> {
public:
AArch64GOTSection(const ELFLinkingContext &ctx);
bool hasGlobalGOTEntry(const Atom *a) const {
return _tlsMap.count(a);
}
const AtomLayout *appendAtom(const Atom *atom) override;
private:
/// \brief Map TLS Atoms to their GOT entry index.
llvm::DenseMap<const Atom *, std::size_t> _tlsMap;
};
} // elf
} // lld
#endif

View File

@ -12,10 +12,24 @@
#include "AArch64ExecutableWriter.h"
#include "AArch64LinkingContext.h"
#include "AArch64TargetHandler.h"
#include "AArch64SectionChunks.h"
using namespace lld;
using namespace elf;
AArch64TargetLayout::AArch64TargetLayout(ELFLinkingContext &ctx) :
TargetLayout(ctx),
_gotSection(new (this->_allocator) AArch64GOTSection(ctx)) {}
AtomSection<ELF64LE> *AArch64TargetLayout::createSection(
StringRef name, int32_t type, DefinedAtom::ContentPermissions permissions,
typename TargetLayout<ELF64LE>::SectionOrder order) {
if (type == DefinedAtom::typeGOT && name == ".got")
return _gotSection;
return TargetLayout<ELF64LE>::createSection(name, type, permissions, order);
}
AArch64TargetHandler::AArch64TargetHandler(AArch64LinkingContext &ctx)
: _ctx(ctx), _targetLayout(new AArch64TargetLayout(ctx)),
_relocationHandler(new AArch64TargetRelocationHandler(*_targetLayout)) {}

View File

@ -17,13 +17,22 @@
namespace lld {
namespace elf {
class AArch64LinkingContext;
class AArch64GOTSection;
class AArch64TargetLayout final : public TargetLayout<ELF64LE> {
typedef llvm::object::Elf_Shdr_Impl<ELF64LE> Elf_Shdr;
public:
AArch64TargetLayout(ELFLinkingContext &ctx) : TargetLayout(ctx) {}
AArch64TargetLayout(ELFLinkingContext &ctx);
AtomSection<ELF64LE> *
createSection(StringRef name, int32_t type,
DefinedAtom::ContentPermissions permissions,
typename TargetLayout<ELF64LE>::SectionOrder order) override;
const AArch64GOTSection &getGOTSection() const { return *_gotSection; }
uint64_t getTPOffset() {
std::call_once(_tpOffOnce, [this]() {
@ -44,6 +53,7 @@ private:
};
private:
AArch64GOTSection *_gotSection;
uint64_t _tpOff = 0;
std::once_flag _tpOffOnce;
};

View File

@ -3,6 +3,8 @@ add_llvm_library(lldAArch64ELFTarget
AArch64TargetHandler.cpp
AArch64RelocationHandler.cpp
AArch64RelocationPass.cpp
AArch64ExecutableWriter.cpp
AArch64SectionChunks.cpp
LINK_LIBS
lldELF
lldReaderWriter

View File

@ -0,0 +1,78 @@
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_AARCH64
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
AddressAlign: 0x0000000000000004
Content: ''
- Name: .data
Type: SHT_PROGBITS
Flags: [ SHF_WRITE, SHF_ALLOC ]
AddressAlign: 0x0000000000000004
Content: ''
- Name: .bss
Type: SHT_NOBITS
Flags: [ SHF_WRITE, SHF_ALLOC ]
AddressAlign: 0x0000000000000004
Content: ''
- Name: .tbss
Type: SHT_NOBITS
Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
AddressAlign: 0x0000000000000004
Content: 00636C616E672076657273696F6E2033
- Name: .comment
Type: SHT_PROGBITS
Flags: [ SHF_MERGE, SHF_STRINGS ]
AddressAlign: 0x0000000000000001
Content: 00636C616E672076657273696F6E20332E372E302028687474703A2F2F6C6C766D2E6F72672F6769742F636C616E672E6769742065653461393664373236383264353237636635353336313135366235656531383662303964363138292028687474703A2F2F6C6C766D2E6F72672F6769742F6C6C766D2E67697420623065376165623639343236646331346637376466626535343533333536366664363866396466632900
- Name: .note.GNU-stack
Type: SHT_PROGBITS
AddressAlign: 0x0000000000000001
Content: ''
Symbols:
Local:
- Name: '$d.0'
Type: STT_TLS
Section: .tbss
- Name: '$d.1'
Section: .comment
- Name: .tbss
Type: STT_TLS
Section: .tbss
- Type: STT_SECTION
Section: .text
- Type: STT_SECTION
Section: .data
- Type: STT_SECTION
Section: .bss
- Type: STT_SECTION
Section: .comment
- Type: STT_SECTION
Section: .note.GNU-stack
Global:
- Name: e0
Type: STT_TLS
Section: .tbss
Size: 0x0000000000000004
- Name: e1
Type: STT_TLS
Section: .tbss
Value: 0x0000000000000004
Size: 0x0000000000000004
- Name: e2
Type: STT_TLS
Section: .tbss
Value: 0x0000000000000008
Size: 0x0000000000000004
- Name: e3
Type: STT_TLS
Section: .tbss
Value: 0x000000000000000C
Size: 0x0000000000000004
...

View File

@ -0,0 +1,147 @@
# Check for initial executable TLS access across different modules. For
# this case compiler will emit R_AARCH64_TLSLD_ADR_PAGE21 and
# R_AARCH64_TLSLD_ADD_LO12_NC static relocations and linker should create
# a R_AARCH64_TLS_TPREL64 dynamic relocation for variable access.
# The test case was generated from following code snippet:
#
# t1.c (initial-exec-tls-1.yaml)
#
# __thread int e0;
# __thread int e1;
# __thread int e2;
# __thread int e3;
#
# t0.c (initial-exec-tls-0.test)
#
# extern __thread int e0;
# extern __thread int e1;
# extern __thread int e2;
# extern __thread int e3;
#
# int main ()
# {
# e0 = 1;
# e1 = 2;
# e1 = 3;
# e1 = 4;
# }
#RUN: yaml2obj -format=elf %p/Inputs/initial-exec-tls-1.yaml -o=%t-t1.o
#RUN: yaml2obj -format=elf %s -o %t-t0.o
#RUN: lld -flavor gnu -target arm64 --noinhibit-exec -o %t.exe %t-t0.o %t-t1.o
#RUN: llvm-readobj -relocations %t.exe | FileCheck %s -check-prefix=CHECKRELOCATION
#RUN: llvm-objdump -s -t %t.exe | FileCheck %s
#CHECKRELOCATION: R_AARCH64_TLS_TPREL64 e0 0x0
#CHECKRELOCATION: R_AARCH64_TLS_TPREL64 e1 0x0
#CHECKRELOCATION: R_AARCH64_TLS_TPREL64 e2 0x0
#CHECKRELOCATION: R_AARCH64_TLS_TPREL64 e3 0x0
#CHECK: Contents of section .text:
#CHECK-NEXT: 4002c0 ff4300d1 e8031f2a e9031e32 0a0000b0 .C.....*...2....
# \_ adrp x10, 401000 (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21)
#CHECK-NEXT: 4002d0 4a4940f9 4bd03bd5 ec030032 6c692ab8 JI@.K.;....2li*.
# \_ ldr x10, [x10,#144] (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
#CHECK-NEXT: 4002e0 0a0000b0 4a4d40f9 ec031f32 6c692ab8 ....JM@....2li*.
# \_ | adrp x10, 401000 (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21)
# \_ ldr x10, [x10,#152] (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
#CHECK-NEXT: 4002f0 0a0000b0 4a5140f9 ec070032 6c692ab8 ....JQ@....2li*.
# \_ | adrp x10, 401000 (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21)
# \_ ldr x10, [x10,#160] (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
#CHECK-NEXT: 400300 0a0000b0 4a5540f9 ec031e32 6c692ab8 ....JU@....2li*.
# \_ | adrp x10, 401000 (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21)
# \_ ldr x10, [x10,#168] (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_AARCH64
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
AddressAlign: 0x0000000000000004
Content: FF4300D1E8031F2AE9031E320A0000904A0140F94BD03BD5EC0300326C692AB80A0000904A0140F9EC031F326C692AB80A0000904A0140F9EC0700326C692AB80A0000904A0140F9EC031E326C692AB8E003082AE90F00B9FF430091C0035FD6
- Name: .rela.text
Type: SHT_RELA
Link: .symtab
AddressAlign: 0x0000000000000008
Info: .text
Relocations:
- Offset: 0x000000000000000C
Symbol: e0
Type: R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
- Offset: 0x0000000000000010
Symbol: e0
Type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
- Offset: 0x0000000000000020
Symbol: e1
Type: R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
- Offset: 0x0000000000000024
Symbol: e1
Type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
- Offset: 0x0000000000000030
Symbol: e2
Type: R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
- Offset: 0x0000000000000034
Symbol: e2
Type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
- Offset: 0x0000000000000040
Symbol: e3
Type: R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
- Offset: 0x0000000000000044
Symbol: e3
Type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
- Name: .data
Type: SHT_PROGBITS
Flags: [ SHF_WRITE, SHF_ALLOC ]
AddressAlign: 0x0000000000000004
Content: ''
- Name: .bss
Type: SHT_NOBITS
Flags: [ SHF_WRITE, SHF_ALLOC ]
AddressAlign: 0x0000000000000004
Content: ''
- Name: .comment
Type: SHT_PROGBITS
Flags: [ SHF_MERGE, SHF_STRINGS ]
AddressAlign: 0x0000000000000001
Content: 00636C616E672076657273696F6E20332E372E302028687474703A2F2F6C6C766D2E6F72672F6769742F636C616E672E6769742065653461393664373236383264353237636635353336313135366235656531383662303964363138292028687474703A2F2F6C6C766D2E6F72672F6769742F6C6C766D2E67697420623065376165623639343236646331346637376466626535343533333536366664363866396466632900
- Name: .note.GNU-stack
Type: SHT_PROGBITS
AddressAlign: 0x0000000000000001
Content: ''
Symbols:
Local:
- Name: '$d.1'
Section: .comment
- Name: '$x.0'
Section: .text
- Type: STT_SECTION
Section: .text
- Type: STT_SECTION
Section: .data
- Type: STT_SECTION
Section: .bss
- Type: STT_SECTION
Section: .comment
- Type: STT_SECTION
Section: .note.GNU-stack
Global:
- Name: e0
Type: STT_TLS
- Name: e1
Type: STT_TLS
- Name: e2
Type: STT_TLS
- Name: e3
Type: STT_TLS
- Name: main
Type: STT_FUNC
Section: .text
Size: 0x0000000000000060
...