Skip to content

Commit c77f5fa

Browse files
committedNov 13, 2014
[ELF] Add CodeModel attribute to the DefinedAtom class
MIPS ELF symbols might contain some additional MIPS-specific flags in the st_other field besides visibility ones. These flags indicate code properties like microMIPS / MIPS16 encoding, position independent code etc. We need to transfer the flags from input objects to the output linked file to write them into the symbol table, adjust symbols addresses etc. I add new attribute CodeModel to the DefinedAtom class to hold target specific flag and to get over YAML/Native format conversion barrier. Other architectures/targets can extend CodeModel enumeration by their own flags. MIPS specific part of this patch adds support for STO_MIPS_MICROMIPS flag. This flag marks microMIPS symbols. Such symbol should: a) Has STO_MIPS_MICROMIPS in the corresponding .symtab record. b) Has adjusted (odd) address in the corresponding .symtab and .dynsym records. llvm-svn: 221864
1 parent 2a18f35 commit c77f5fa

12 files changed

+270
-8
lines changed
 

‎lld/include/lld/Core/DefinedAtom.h

+12
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,15 @@ class DefinedAtom : public Atom {
194194
dynamicExportAlways,
195195
};
196196

197+
// Attributes describe a code model used by the atom.
198+
enum CodeModel {
199+
codeNA, // no specific code model
200+
codeMipsPIC, // PIC function in a PIC / non-PIC mixed file
201+
codeMipsMicro, // microMIPS instruction encoding
202+
codeMipsMicroPIC, // microMIPS instruction encoding + PIC
203+
codeMips16, // MIPS-16 instruction encoding
204+
};
205+
197206
struct Alignment {
198207
Alignment(int p2, int m = 0)
199208
: powerOf2(p2)
@@ -266,6 +275,9 @@ class DefinedAtom : public Atom {
266275
return dynamicExportNormal;
267276
}
268277

278+
/// \brief Code model used by the atom.
279+
virtual CodeModel codeModel() const { return codeNA; }
280+
269281
/// \brief Returns the OS memory protections required for this atom's content
270282
/// at runtime.
271283
///

‎lld/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h

+9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
namespace lld {
1818
namespace elf {
1919

20+
template <typename ELFT> class MipsSymbolTable;
2021
template <typename ELFT> class MipsDynamicSymbolTable;
2122
template <typename ELFT> class MipsTargetLayout;
2223

@@ -39,6 +40,7 @@ class MipsDynamicLibraryWriter : public DynamicLibraryWriter<ELFT> {
3940
return std::error_code();
4041
}
4142

43+
LLD_UNIQUE_BUMP_PTR(SymbolTable<ELFT>) createSymbolTable() override;
4244
LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>) createDynamicTable() override;
4345

4446
LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>)
@@ -73,6 +75,13 @@ void MipsDynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() {
7375
_writeHelper.finalizeMipsRuntimeAtomValues();
7476
}
7577

78+
template <class ELFT>
79+
LLD_UNIQUE_BUMP_PTR(SymbolTable<ELFT>)
80+
MipsDynamicLibraryWriter<ELFT>::createSymbolTable() {
81+
return LLD_UNIQUE_BUMP_PTR(SymbolTable<ELFT>)(new (
82+
this->_alloc) MipsSymbolTable<ELFT>(_mipsContext));
83+
}
84+
7685
/// \brief create dynamic table
7786
template <class ELFT>
7887
LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>)

‎lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h

+15
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,21 @@ class MipsELFDefinedAtom : public ELFDefinedAtom<ELFT> {
6060
const MipsELFFile<ELFT>& file() const override {
6161
return static_cast<const MipsELFFile<ELFT> &>(this->_owningFile);
6262
}
63+
64+
DefinedAtom::CodeModel codeModel() const override {
65+
switch (this->_symbol->st_other & llvm::ELF::STO_MIPS_MIPS16) {
66+
case llvm::ELF::STO_MIPS_MIPS16:
67+
return DefinedAtom::codeMips16;
68+
case llvm::ELF::STO_MIPS_PIC:
69+
return DefinedAtom::codeMipsPIC;
70+
case llvm::ELF::STO_MIPS_MICROMIPS:
71+
return DefinedAtom::codeMipsMicro;
72+
case llvm::ELF::STO_MIPS_MICROMIPS | llvm::ELF::STO_MIPS_PIC:
73+
return DefinedAtom::codeMipsMicroPIC;
74+
default:
75+
return DefinedAtom::codeNA;
76+
}
77+
}
6378
};
6479

6580
template <class ELFT> class MipsELFFile : public ELFFile<ELFT> {

‎lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h

+8
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class MipsExecutableWriter : public ExecutableWriter<ELFT> {
3939
return std::error_code();
4040
}
4141

42+
LLD_UNIQUE_BUMP_PTR(SymbolTable<ELFT>) createSymbolTable() override;
4243
LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>) createDynamicTable() override;
4344

4445
LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>)
@@ -113,6 +114,13 @@ void MipsExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
113114
_writeHelper.finalizeMipsRuntimeAtomValues();
114115
}
115116

117+
template <class ELFT>
118+
LLD_UNIQUE_BUMP_PTR(SymbolTable<ELFT>)
119+
MipsExecutableWriter<ELFT>::createSymbolTable() {
120+
return LLD_UNIQUE_BUMP_PTR(SymbolTable<ELFT>)(new (
121+
this->_alloc) MipsSymbolTable<ELFT>(_mipsContext));
122+
}
123+
116124
/// \brief create dynamic table
117125
template <class ELFT>
118126
LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>)

‎lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h

+55-6
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,48 @@ class MipsTargetHandler final : public DefaultTargetHandler<Mips32ElELFType> {
135135
std::unique_ptr<MipsTargetRelocationHandler> _relocationHandler;
136136
};
137137

138+
template <class ELFT> class MipsSymbolTable : public SymbolTable<ELFT> {
139+
public:
140+
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
141+
142+
MipsSymbolTable(const MipsLinkingContext &ctx)
143+
: SymbolTable<ELFT>(ctx, ".symtab",
144+
DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE) {}
145+
146+
void addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
147+
int64_t addr) override {
148+
SymbolTable<ELFT>::addDefinedAtom(sym, da, addr);
149+
150+
switch (da->codeModel()) {
151+
case DefinedAtom::codeMipsMicro:
152+
sym.st_other |= llvm::ELF::STO_MIPS_MICROMIPS;
153+
break;
154+
case DefinedAtom::codeMipsMicroPIC:
155+
sym.st_other |= llvm::ELF::STO_MIPS_MICROMIPS | llvm::ELF::STO_MIPS_PIC;
156+
break;
157+
default:
158+
break;
159+
}
160+
}
161+
162+
void finalize(bool sort = true) override {
163+
SymbolTable<ELFT>::finalize(sort);
164+
165+
for (auto &ste : this->_symbolTable) {
166+
if (!ste._atom)
167+
continue;
168+
if (const auto *da = dyn_cast<DefinedAtom>(ste._atom)) {
169+
if (da->codeModel() == DefinedAtom::codeMipsMicro ||
170+
da->codeModel() == DefinedAtom::codeMipsMicroPIC) {
171+
// Adjust dynamic microMIPS symbol value. That allows a dynamic
172+
// linker to recognize and handle this symbol correctly.
173+
ste._symbol.st_value = ste._symbol.st_value | 1;
174+
}
175+
}
176+
}
177+
}
178+
};
179+
138180
template <class ELFT>
139181
class MipsDynamicSymbolTable : public DynamicSymbolTable<ELFT> {
140182
public:
@@ -157,23 +199,30 @@ class MipsDynamicSymbolTable : public DynamicSymbolTable<ELFT> {
157199
}
158200

159201
void finalize() override {
202+
DynamicSymbolTable<ELFT>::finalize();
203+
160204
const auto &pltSection = _targetLayout.getPLTSection();
161205

162-
// Under some conditions a dynamic symbol table record should hold a symbol
163-
// value of the corresponding PLT entry. For details look at the PLT entry
164-
// creation code in the class MipsRelocationPass. Let's update atomLayout
165-
// fields for such symbols.
166206
for (auto &ste : this->_symbolTable) {
167207
if (!ste._atom)
168208
continue;
169209
if (auto *layout = pltSection.findPLTLayout(ste._atom)) {
210+
// Under some conditions a dynamic symbol table record should hold
211+
// a symbol value of the corresponding PLT entry. For details look
212+
// at the PLT entry creation code in the class MipsRelocationPass.
213+
// Let's update atomLayout fields for such symbols.
170214
assert(!ste._atomLayout);
171215
ste._symbol.st_value = layout->_virtualAddr;
172216
ste._symbol.st_other |= ELF::STO_MIPS_PLT;
217+
} else if (const auto *da = dyn_cast<DefinedAtom>(ste._atom)) {
218+
if (da->codeModel() == DefinedAtom::codeMipsMicro ||
219+
da->codeModel() == DefinedAtom::codeMipsMicroPIC) {
220+
// Adjust dynamic microMIPS symbol value. That allows a dynamic
221+
// linker to recognize and handle this symbol correctly.
222+
ste._symbol.st_value = ste._symbol.st_value | 1;
223+
}
173224
}
174225
}
175-
176-
DynamicSymbolTable<Mips32ElELFType>::finalize();
177226
}
178227

179228
private:

‎lld/lib/ReaderWriter/ELF/OutputELFWriter.h

+11-2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ class OutputELFWriter : public ELFWriter {
100100
// This is a hook for creating default dynamic entries
101101
virtual void createDefaultDynamicEntries() {}
102102

103+
/// \brief Create symbol table.
104+
virtual LLD_UNIQUE_BUMP_PTR(SymbolTable<ELFT>) createSymbolTable();
105+
103106
/// \brief create dynamic table.
104107
virtual LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>) createDynamicTable();
105108

@@ -284,8 +287,7 @@ template <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() {
284287
_layout.setHeader(_elfHeader.get());
285288
_layout.setProgramHeader(_programHeader.get());
286289

287-
_symtab.reset(new (_alloc) SymbolTable<ELFT>(
288-
_context, ".symtab", DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE));
290+
_symtab = std::move(this->createSymbolTable());
289291
_strtab.reset(new (_alloc) StringTable<ELFT>(
290292
_context, ".strtab", DefaultLayout<ELFT>::ORDER_STRING_TABLE));
291293
_shstrtab.reset(new (_alloc) StringTable<ELFT>(
@@ -336,6 +338,13 @@ template <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() {
336338
}
337339
}
338340

341+
template <class ELFT>
342+
LLD_UNIQUE_BUMP_PTR(SymbolTable<ELFT>)
343+
OutputELFWriter<ELFT>::createSymbolTable() {
344+
return LLD_UNIQUE_BUMP_PTR(SymbolTable<ELFT>)(new (_alloc) SymbolTable<ELFT>(
345+
this->_context, ".symtab", DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE));
346+
}
347+
339348
/// \brief create dynamic table
340349
template <class ELFT>
341350
LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>)

‎lld/lib/ReaderWriter/Native/NativeFileFormat.h

+1
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ struct NativeAtomAttributesV1 {
155155
uint8_t dynamicExport;
156156
uint8_t permissions;
157157
uint8_t alias;
158+
uint8_t codeModel;
158159
};
159160

160161

‎lld/lib/ReaderWriter/Native/ReaderNative.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ class NativeDefinedAtomV1 : public DefinedAtom {
9090
return (DynamicExport)attributes().dynamicExport;
9191
}
9292

93+
DefinedAtom::CodeModel codeModel() const override {
94+
return DefinedAtom::CodeModel(attributes().codeModel);
95+
}
96+
9397
DefinedAtom::ContentPermissions permissions() const override {
9498
return (DefinedAtom::ContentPermissions)(attributes().permissions);
9599
}

‎lld/lib/ReaderWriter/Native/WriterNative.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,7 @@ class Writer : public lld::Writer {
426426
= atom.sectionChoice() << 4 | atom.sectionPosition();
427427
attrs.deadStrip = atom.deadStrip();
428428
attrs.dynamicExport = atom.dynamicExport();
429+
attrs.codeModel = atom.codeModel();
429430
attrs.permissions = atom.permissions();
430431
return attrs;
431432
}

‎lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,16 @@ template <> struct ScalarEnumerationTraits<lld::DefinedAtom::DynamicExport> {
386386
}
387387
};
388388

389+
template <> struct ScalarEnumerationTraits<lld::DefinedAtom::CodeModel> {
390+
static void enumeration(IO &io, lld::DefinedAtom::CodeModel &value) {
391+
io.enumCase(value, "none", lld::DefinedAtom::codeNA);
392+
io.enumCase(value, "mips-pic", lld::DefinedAtom::codeMipsPIC);
393+
io.enumCase(value, "mips-micro", lld::DefinedAtom::codeMipsMicro);
394+
io.enumCase(value, "mips-micro-pic", lld::DefinedAtom::codeMipsMicroPIC);
395+
io.enumCase(value, "mips-16", lld::DefinedAtom::codeMips16);
396+
}
397+
};
398+
389399
template <>
390400
struct ScalarEnumerationTraits<lld::DefinedAtom::ContentPermissions> {
391401
static void enumeration(IO &io, lld::DefinedAtom::ContentPermissions &value) {
@@ -809,6 +819,7 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
809819
_alignment(atom->alignment()), _sectionChoice(atom->sectionChoice()),
810820
_sectionPosition(atom->sectionPosition()),
811821
_deadStrip(atom->deadStrip()), _dynamicExport(atom->dynamicExport()),
822+
_codeModel(atom->codeModel()),
812823
_permissions(atom->permissions()), _size(atom->size()),
813824
_sectionName(atom->customSectionName()) {
814825
for (const lld::Reference *r : *atom)
@@ -859,6 +870,7 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
859870
SectionPosition sectionPosition() const override { return _sectionPosition; }
860871
DeadStripKind deadStrip() const override { return _deadStrip; }
861872
DynamicExport dynamicExport() const override { return _dynamicExport; }
873+
CodeModel codeModel() const override { return _codeModel; }
862874
ContentPermissions permissions() const override { return _permissions; }
863875
void setGroupChild(bool val) { _isGroupChild = val; }
864876
bool isGroupChild() const { return _isGroupChild; }
@@ -904,6 +916,7 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
904916
SectionPosition _sectionPosition;
905917
DeadStripKind _deadStrip;
906918
DynamicExport _dynamicExport;
919+
CodeModel _codeModel;
907920
ContentPermissions _permissions;
908921
uint32_t _ordinal;
909922
std::vector<ImplicitHex8> _content;
@@ -951,6 +964,7 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
951964
DefinedAtom::deadStripNormal);
952965
io.mapOptional("dynamic-export", keys->_dynamicExport,
953966
DefinedAtom::dynamicExportNormal);
967+
io.mapOptional("code-model", keys->_codeModel, DefinedAtom::codeNA);
954968
// default permissions based on content type
955969
io.mapOptional("permissions", keys->_permissions,
956970
DefinedAtom::permissions(
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# RUN: lld -core %s | FileCheck %s
2+
3+
#
4+
# Test that code model attributes are preserved
5+
#
6+
7+
---
8+
defined-atoms:
9+
- name: _def
10+
---
11+
defined-atoms:
12+
- name: _none
13+
code-model: none
14+
---
15+
defined-atoms:
16+
- name: _mips_pic
17+
code-model: mips-pic
18+
---
19+
defined-atoms:
20+
- name: _mips_micro
21+
code-model: mips-micro
22+
---
23+
defined-atoms:
24+
- name: _mips_micro_pic
25+
code-model: mips-micro-pic
26+
---
27+
defined-atoms:
28+
- name: _mips_16
29+
code-model: mips-16
30+
...
31+
32+
# CHECK: name: _def
33+
# CHECK-NOT: code-model: mips-pic
34+
# CHECK-NOT: code-model: mips-micro
35+
# CHECK-NOT: code-model: mips-micro-pic
36+
# CHECK-NOT: code-model: mips-16
37+
# CHECK: name: _none
38+
# CHECK-NOT: code-model: mips-pic
39+
# CHECK-NOT: code-model: mips-micro
40+
# CHECK-NOT: code-model: mips-micro-pic
41+
# CHECK-NOT: code-model: mips-16
42+
# CHECK: name: _mips_pic
43+
# CHECK: code-model: mips-pic
44+
# CHECK: name: _mips_micro
45+
# CHECK: code-model: mips-micro
46+
# CHECK: name: _mips_micro_pic
47+
# CHECK: code-model: mips-micro-pic
48+
# CHECK: name: _mips_16
49+
# CHECK: code-model: mips-16
50+
# CHECK: ...

0 commit comments

Comments
 (0)
Please sign in to comment.