|
7 | 7 | //===----------------------------------------------------------------------===//
|
8 | 8 |
|
9 | 9 | #include "SymbolTable.h"
|
| 10 | +#include "ConcatOutputSection.h" |
10 | 11 | #include "Config.h"
|
11 | 12 | #include "InputFiles.h"
|
12 | 13 | #include "Symbols.h"
|
| 14 | +#include "SyntheticSections.h" |
13 | 15 | #include "lld/Common/ErrorHandler.h"
|
14 | 16 | #include "lld/Common/Memory.h"
|
15 | 17 |
|
@@ -196,7 +198,73 @@ Defined *SymbolTable::addSynthetic(StringRef name, InputSection *isec,
|
196 | 198 | return s;
|
197 | 199 | }
|
198 | 200 |
|
| 201 | +enum class Boundary { |
| 202 | + Start, |
| 203 | + End, |
| 204 | +}; |
| 205 | + |
| 206 | +static void handleSectionBoundarySymbol(const Undefined &sym, StringRef segSect, |
| 207 | + Boundary which) { |
| 208 | + StringRef segName, sectName; |
| 209 | + std::tie(segName, sectName) = segSect.split('$'); |
| 210 | + |
| 211 | + // Attach the symbol to any InputSection that will end up in the right |
| 212 | + // OutputSection -- it doesn't matter which one we pick. |
| 213 | + // Don't bother looking through inputSections for a matching |
| 214 | + // ConcatInputSection -- we need to create ConcatInputSection for |
| 215 | + // non-existing sections anyways, and that codepath works even if we should |
| 216 | + // already have a ConcatInputSection with the right name. |
| 217 | + |
| 218 | + OutputSection *osec = nullptr; |
| 219 | + // This looks for __TEXT,__cstring etc. |
| 220 | + for (SyntheticSection *ssec : syntheticSections) |
| 221 | + if (ssec->segname == segName && ssec->name == sectName) { |
| 222 | + osec = ssec->isec->parent; |
| 223 | + break; |
| 224 | + } |
| 225 | + |
| 226 | + if (!osec) { |
| 227 | + ConcatInputSection *isec = make<ConcatInputSection>(segName, sectName); |
| 228 | + |
| 229 | + // This runs after markLive() and is only called for Undefineds that are |
| 230 | + // live. Marking the isec live ensures an OutputSection is created that the |
| 231 | + // start/end symbol can refer to. |
| 232 | + assert(sym.isLive()); |
| 233 | + isec->live = true; |
| 234 | + |
| 235 | + // This runs after gatherInputSections(), so need to explicitly set parent |
| 236 | + // and add to inputSections. |
| 237 | + osec = isec->parent = ConcatOutputSection::getOrCreateForInput(isec); |
| 238 | + inputSections.push_back(isec); |
| 239 | + } |
| 240 | + |
| 241 | + Defined *boundarySym = symtab->addSynthetic( |
| 242 | + sym.getName(), /*isec=*/nullptr, /*value=*/-1, /*isPrivateExtern=*/true, |
| 243 | + /*includeInSymtab=*/false, /*referencedDynamically=*/false); |
| 244 | + if (which == Boundary::Start) |
| 245 | + osec->sectionStartSymbols.push_back(boundarySym); |
| 246 | + else |
| 247 | + osec->sectionEndSymbols.push_back(boundarySym); |
| 248 | +} |
| 249 | + |
| 250 | +static void handleSegmentBoundarySymbol(const Undefined &sym, StringRef segName, |
| 251 | + Boundary which) { |
| 252 | + // FIXME |
| 253 | + error("segment$start$ and segment$end$ symbols are not yet implemented"); |
| 254 | +} |
| 255 | + |
199 | 256 | void lld::macho::treatUndefinedSymbol(const Undefined &sym, StringRef source) {
|
| 257 | + // Handle start/end symbols. |
| 258 | + StringRef name = sym.getName(); |
| 259 | + if (name.consume_front("section$start$")) |
| 260 | + return handleSectionBoundarySymbol(sym, name, Boundary::Start); |
| 261 | + if (name.consume_front("section$end$")) |
| 262 | + return handleSectionBoundarySymbol(sym, name, Boundary::End); |
| 263 | + if (name.consume_front("segment$start$")) |
| 264 | + return handleSegmentBoundarySymbol(sym, name, Boundary::Start); |
| 265 | + if (name.consume_front("segment$end$")) |
| 266 | + return handleSegmentBoundarySymbol(sym, name, Boundary::End); |
| 267 | + |
200 | 268 | // Handle -U.
|
201 | 269 | if (config->explicitDynamicLookups.count(sym.getName())) {
|
202 | 270 | symtab->addDynamicLookup(sym.getName());
|
|
0 commit comments