[lld][ELF] Assign sectionChoice properly to ELF atoms
This sets the sectionChoice property for DefinedAtoms. The output section name is derived by the property of the atom. This also decreases native file size. Adds a test. llvm-svn: 190840
This commit is contained in:
parent
36399e6b68
commit
063b75013f
|
@ -16,6 +16,7 @@
|
||||||
#include "lld/ReaderWriter/Simple.h"
|
#include "lld/ReaderWriter/Simple.h"
|
||||||
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -376,9 +377,20 @@ public:
|
||||||
|
|
||||||
// Do we have a choice for ELF? All symbols live in explicit sections.
|
// Do we have a choice for ELF? All symbols live in explicit sections.
|
||||||
virtual SectionChoice sectionChoice() const {
|
virtual SectionChoice sectionChoice() const {
|
||||||
if (_symbol->st_shndx > llvm::ELF::SHN_LORESERVE)
|
switch (contentType()) {
|
||||||
return sectionBasedOnContent;
|
case typeCode:
|
||||||
|
case typeData:
|
||||||
|
case typeZeroFill:
|
||||||
|
case typeThreadZeroFill:
|
||||||
|
case typeThreadData:
|
||||||
|
case typeConstant:
|
||||||
|
if ((_sectionName == ".text") || (_sectionName == ".data") ||
|
||||||
|
(_sectionName == ".bss") || (_sectionName == ".rodata") ||
|
||||||
|
(_sectionName == ".tdata") || (_sectionName == ".tbss"))
|
||||||
|
return sectionBasedOnContent;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
return sectionCustomRequired;
|
return sectionCustomRequired;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,8 +172,7 @@ public:
|
||||||
int32_t contentPermissions);
|
int32_t contentPermissions);
|
||||||
|
|
||||||
/// \brief This maps the input sections to the output section names
|
/// \brief This maps the input sections to the output section names
|
||||||
virtual StringRef getSectionName(StringRef name, const int32_t contentType,
|
virtual StringRef getSectionName(const DefinedAtom *da) const;
|
||||||
const int32_t contentPermissions);
|
|
||||||
|
|
||||||
/// \brief Gets or creates a section.
|
/// \brief Gets or creates a section.
|
||||||
AtomSection<ELFT> *getSection(
|
AtomSection<ELFT> *getSection(
|
||||||
|
@ -372,29 +371,35 @@ Layout::SectionOrder DefaultLayout<ELFT>::getSectionOrder(
|
||||||
|
|
||||||
/// \brief This maps the input sections to the output section names
|
/// \brief This maps the input sections to the output section names
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
StringRef DefaultLayout<ELFT>::getSectionName(
|
StringRef DefaultLayout<ELFT>::getSectionName(const DefinedAtom *da) const {
|
||||||
StringRef name, const int32_t contentType,
|
if (da->sectionChoice() == DefinedAtom::sectionBasedOnContent) {
|
||||||
const int32_t contentPermissions) {
|
switch (da->contentType()) {
|
||||||
if ((contentType == DefinedAtom::typeZeroFill) ||
|
case DefinedAtom::typeCode:
|
||||||
(contentType == DefinedAtom::typeZeroFillFast))
|
return ".text";
|
||||||
return ".bss";
|
case DefinedAtom::typeData:
|
||||||
if (name.startswith(".text"))
|
return ".data";
|
||||||
return ".text";
|
case DefinedAtom::typeConstant:
|
||||||
if (name.startswith(".rodata"))
|
return ".rodata";
|
||||||
return ".rodata";
|
case DefinedAtom::typeZeroFill:
|
||||||
if (name.startswith(".gcc_except_table"))
|
return ".bss";
|
||||||
return ".gcc_except_table";
|
case DefinedAtom::typeThreadData:
|
||||||
if (name.startswith(".data.rel.ro"))
|
return ".tdata";
|
||||||
return ".data.rel.ro";
|
case DefinedAtom::typeThreadZeroFill:
|
||||||
if (name.startswith(".data.rel.local"))
|
return ".tbss";
|
||||||
return ".data.rel.local";
|
default:
|
||||||
if (name.startswith(".data"))
|
break;
|
||||||
return ".data";
|
}
|
||||||
if (name.startswith(".tdata"))
|
}
|
||||||
return ".tdata";
|
return llvm::StringSwitch<StringRef>(da->customSectionName())
|
||||||
if (name.startswith(".tbss"))
|
.StartsWith(".text", ".text")
|
||||||
return ".tbss";
|
.StartsWith(".rodata", ".rodata")
|
||||||
return name;
|
.StartsWith(".gcc_except_table", ".gcc_except_table")
|
||||||
|
.StartsWith(".data.rel.ro", ".data.rel.ro")
|
||||||
|
.StartsWith(".data.rel.local", ".data.rel.local")
|
||||||
|
.StartsWith(".data", ".data")
|
||||||
|
.StartsWith(".tdata", ".tdata")
|
||||||
|
.StartsWith(".tbss", ".tbss")
|
||||||
|
.Default(da->customSectionName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Gets the segment for a output section
|
/// \brief Gets the segment for a output section
|
||||||
|
@ -519,12 +524,11 @@ ErrorOr<const lld::AtomLayout &> DefaultLayout<ELFT>::addAtom(const Atom *atom)
|
||||||
// -noinhibit-exec.
|
// -noinhibit-exec.
|
||||||
if (definedAtom->contentType() == DefinedAtom::typeUnknown)
|
if (definedAtom->contentType() == DefinedAtom::typeUnknown)
|
||||||
return make_error_code(llvm::errc::invalid_argument);
|
return make_error_code(llvm::errc::invalid_argument);
|
||||||
StringRef sectionName = definedAtom->customSectionName();
|
|
||||||
const DefinedAtom::ContentPermissions permissions =
|
const DefinedAtom::ContentPermissions permissions =
|
||||||
definedAtom->permissions();
|
definedAtom->permissions();
|
||||||
const DefinedAtom::ContentType contentType = definedAtom->contentType();
|
const DefinedAtom::ContentType contentType = definedAtom->contentType();
|
||||||
|
|
||||||
sectionName = getSectionName(sectionName, contentType, permissions);
|
StringRef sectionName = getSectionName(definedAtom);
|
||||||
AtomSection<ELFT> *section =
|
AtomSection<ELFT> *section =
|
||||||
getSection(sectionName, contentType, permissions);
|
getSection(sectionName, contentType, permissions);
|
||||||
// Add runtime relocations to the .rela section.
|
// Add runtime relocations to the .rela section.
|
||||||
|
|
|
@ -103,13 +103,15 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief This maps the input sections to the output section names
|
/// \brief This maps the input sections to the output section names
|
||||||
virtual StringRef getSectionName(StringRef name, const int32_t contentType,
|
virtual StringRef getSectionName(const DefinedAtom *da) const {
|
||||||
const int32_t contentPermissions) {
|
switch (da->contentType()) {
|
||||||
if ((contentType == DefinedAtom::typeDataFast) ||
|
case DefinedAtom::typeDataFast:
|
||||||
(contentType == DefinedAtom::typeZeroFillFast))
|
case DefinedAtom::typeZeroFillFast:
|
||||||
return ".sdata";
|
return ".sdata";
|
||||||
return DefaultLayout<HexagonELFType>::getSectionName(name, contentType,
|
default:
|
||||||
contentPermissions);
|
break;
|
||||||
|
}
|
||||||
|
return DefaultLayout<HexagonELFType>::getSectionName(da);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Gets or creates a section.
|
/// \brief Gets or creates a section.
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
# This tests that we are able to properly set the sectionChoice for DefinedAtoms
|
||||||
|
RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/zerosizedsection.o \
|
||||||
|
RUN: --noinhibit-exec -o %t -emit-yaml
|
||||||
|
RUN: FileCheck %s < %t
|
||||||
|
|
||||||
|
CHECK-NOT: section-choice: sectionCustomRequired
|
||||||
|
|
|
@ -12,8 +12,6 @@ mergeAtoms: scope: global
|
||||||
mergeAtoms: type: data
|
mergeAtoms: type: data
|
||||||
mergeAtoms: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
|
mergeAtoms: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
|
||||||
mergeAtoms: alignment: 2^3
|
mergeAtoms: alignment: 2^3
|
||||||
mergeAtoms: section-choice: custom-required
|
|
||||||
mergeAtoms: section-name: .data
|
|
||||||
mergeAtoms: references:
|
mergeAtoms: references:
|
||||||
mergeAtoms: - kind: R_X86_64_64
|
mergeAtoms: - kind: R_X86_64_64
|
||||||
mergeAtoms: offset: 3
|
mergeAtoms: offset: 3
|
||||||
|
|
Loading…
Reference in New Issue