forked from rui314/mold
-
Notifications
You must be signed in to change notification settings - Fork 0
/
input_sections.cc
154 lines (139 loc) · 4.65 KB
/
input_sections.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "mold.h"
#include <limits>
template <typename E>
InputSection<E>::InputSection(Context<E> &ctx, ObjectFile<E> &file,
const ElfShdr<E> &shdr, std::string_view name,
std::string_view contents, i64 section_idx)
: file(file), shdr(shdr), nameptr(name.data()), namelen(name.size()),
contents(contents), section_idx(section_idx) {
// As a special case, we want to map .ctors and .dtors to
// .init_array and .fini_array, respectively. However, old CRT
// object files are not compatible with this translation, so we need
// to keep them as-is if a section came from crtbegin.o or crtend.o.
//
// Yeah, this is an ugly hack, but the fundamental problem is that
// we have two different mechanism, ctors/dtors and init_array/fini_array
// for the same purpose. The latter was introduced to replace the
// former, but as it is often the case, the former still lingers
// around, so we need to keep this code to conver the old mechanism
// to the new one.
std::string_view stem = path_filename(file.filename);
if (stem != "crtbegin.o" && stem != "crtend.o" &&
stem != "crtbeginS.o" && stem != "crtendS.o") {
if (name == ".ctors" || name.starts_with(".ctors."))
name = ".init_array";
else if (name == ".dtors" || name.starts_with(".dtors."))
name = ".fini_array";
}
output_section =
OutputSection<E>::get_instance(ctx, name, shdr.sh_type, shdr.sh_flags);
}
template <typename E>
void InputSection<E>::write_to(Context<E> &ctx, u8 *buf) {
if (shdr.sh_type == SHT_NOBITS || shdr.sh_size == 0)
return;
// Copy data
memcpy(buf, contents.data(), contents.size());
// Apply relocations
if (shdr.sh_flags & SHF_ALLOC)
apply_reloc_alloc(ctx, buf);
else
apply_reloc_nonalloc(ctx, buf);
// As a special case, .ctors and .dtors section contents are
// reversed. These sections are now obsolete and mapped to
// .init_array and .fini_array, but they have to be reversed to
// maintain the original semantics.
bool init_fini = output_section->name == ".init_array" ||
output_section->name == ".fini_array";
bool ctors_dtors = name().starts_with(".ctors") ||
name().starts_with(".dtors");
if (init_fini && ctors_dtors)
std::reverse((typename E::WordTy *)buf,
(typename E::WordTy *)(buf + shdr.sh_size));
}
template <typename E>
static i64 get_output_type(Context<E> &ctx) {
if (ctx.arg.shared)
return 0;
if (ctx.arg.pie)
return 1;
return 2;
}
template <typename E>
static i64 get_sym_type(Context<E> &ctx, Symbol<E> &sym) {
if (sym.is_absolute(ctx))
return 0;
if (!sym.is_imported)
return 1;
if (sym.get_type() != STT_FUNC)
return 2;
return 3;
}
template <typename E>
void InputSection<E>::dispatch(Context<E> &ctx, Action table[3][4], i64 i) {
std::span<ElfRel<E>> rels = get_rels(ctx);
const ElfRel<E> &rel = rels[i];
Symbol<E> &sym = *file.symbols[rel.r_sym];
bool is_writable = (shdr.sh_flags & SHF_WRITE);
Action action = table[get_output_type(ctx)][get_sym_type(ctx, sym)];
switch (action) {
case NONE:
return;
case ERROR:
break;
case COPYREL:
if (!ctx.arg.z_copyreloc && !sym.esym().is_undef_weak())
break;
if (sym.esym().st_visibility == STV_PROTECTED)
Error(ctx) << *this << ": cannot make copy relocation for "
<< " protected symbol '" << sym << "', defined in "
<< *sym.file;
sym.flags |= NEEDS_COPYREL;
return;
case PLT:
sym.flags |= NEEDS_PLT;
return;
case DYNREL:
if (!is_writable) {
if (ctx.arg.z_text)
break;
ctx.has_textrel = true;
}
sym.flags |= NEEDS_DYNSYM;
rel_exprs[i] = R_DYN;
file.num_dynrel++;
return;
case BASEREL:
if (!is_writable) {
if (ctx.arg.z_text)
break;
ctx.has_textrel = true;
}
rel_exprs[i] = R_BASEREL;
file.num_dynrel++;
return;
default:
unreachable(ctx);
}
Error(ctx) << *this << ": " << rel_to_string<E>(rel.r_type)
<< " relocation against symbol `" << sym
<< "' can not be used; recompile with -fPIE";
}
template <typename E>
void InputSection<E>::report_undef(Context<E> &ctx, Symbol<E> &sym) {
switch (ctx.arg.unresolved_symbols) {
case UnresolvedKind::ERROR:
Error(ctx) << "undefined symbol: " << file << ": " << sym;
break;
case UnresolvedKind::WARN:
Warn(ctx) << "undefined symbol: " << file << ": " << sym;
break;
case UnresolvedKind::IGNORE:
break;
}
}
#define INSTANTIATE(E) \
template class InputSection<E>;
INSTANTIATE(X86_64);
INSTANTIATE(I386);
INSTANTIATE(AARCH64);