Changeset View
Standalone View
ELF/Arch/PPC64.cpp
Show First 20 Lines • Show All 100 Lines • ▼ Show 20 Line(s) | |||||
101 | bool elf::isPPC64SmallCodeModelReloc(RelType Type) { | 101 | bool elf::isPPC64SmallCodeModelReloc(RelType Type) { | ||
102 | // List is not yet complete, at the very least the got based tls related | 102 | // List is not yet complete, at the very least the got based tls related | ||
103 | // relocations need to be added, and we need to determine how the section | 103 | // relocations need to be added, and we need to determine how the section | ||
104 | // sorting interacts with the thread pointer and dynamic thread pointer | 104 | // sorting interacts with the thread pointer and dynamic thread pointer | ||
105 | // relative tls relocations. | 105 | // relative tls relocations. | ||
106 | return Type == R_PPC64_GOT16 || Type == R_PPC64_TOC16 || | 106 | return Type == R_PPC64_GOT16 || Type == R_PPC64_TOC16 || | ||
107 | Type == R_PPC64_TOC16_DS; | 107 | Type == R_PPC64_TOC16_DS; | ||
108 | } | 108 | } | ||
109 | 109 | | |||
grimar: Warnings and error messages should start from the lowercase. | |||||
Not Done ReplyIsn't this an error? ruiu: Isn't this an error? | |||||
Not Done ReplyIdeally it would be, however I found a gcc bug where it emits a toc entry without a corresponding relocation. This causes the look ups for any relocations after the skipped one to fail. I am still trying to cut the problem down to something smaller so I can understand it better (and open a bug report to get it fixed), but it seems that the rest of the codegen is valid (ie nothing tries to read or write to the toc entry missing the relocation). I don't think the problem is prevalent enough to warrant changing to a slower scan of the relocations in the case we do find a mismatch, and because the rest of the codegen is 'good' I don't think we should emit an error either. sfertile: Ideally it would be, however I found a gcc bug where it emits a toc entry without a… | |||||
Not Done ReplyI've got some clarification from the ppc64 gcc/binutils developers and although the case I found was a bug , both gcc and xlc will emit values that don't need relocations into the .toc section in certian circumstances. I'll have to fix the lookup logic to deal with the fact I can't assume every .toc entry has a relocation. sfertile: I've got some clarification from the ppc64 gcc/binutils developers and although the case I… | |||||
110 | // Searches through the relocations in TocSec looking for the one with | ||||
Not Done ReplyIt feels this comment can be improved. IIUC, this function scans relocations for a given section to find one whose offset is the same as a given offset. Is this correct? If so, can you add something like that as a comment? ruiu: It feels this comment can be improved. IIUC, this function scans relocations for a given… | |||||
111 | // matching Offset. | ||||
112 | template <typename ELFT> | ||||
113 | static std::pair<Defined *, int64_t> getSymAndAddend(InputSectionBase *TocSec, | ||||
114 | uint64_t Offset) { | ||||
Done ReplyI'd define an alias at the beginning of this function like this: typedef typename ELFT::Rela RelTy; ruiu: I'd define an alias at the beginning of this function like this:
typedef typename ELFT::Rela… | |||||
115 | typedef typename ELFT::Rela RelaTy; | ||||
Done Replyif (Relas.empty()) MaskRay: if (Relas.empty()) | |||||
116 | ArrayRef<RelaTy> Relas = TocSec->template relas<ELFT>(); | ||||
117 | if (Relas.empty()) | ||||
118 | return {}; | ||||
119 | | ||||
Done ReplyThe same. grimar: The same. | |||||
Not Done ReplyDitto ruiu: Ditto | |||||
120 | // Extracts the Symbol and addend from a relocation. | ||||
Done ReplyWhen we define a local helper lambda function inside a function, we capture variables just by [&] instead of explicitly enumerating variables. ruiu: When we define a local helper lambda function inside a function, we capture variables just by `… | |||||
Done ReplyI've updated to follow suit, but can I ask the rational behind this? For a lambda as small as this one its easy to see that only one variable is used and its not modified, but in general I would prefer to be explicit and not capture anymore then I used. sfertile: I've updated to follow suit, but can I ask the rational behind this? For a lambda as small as… | |||||
121 | auto SymAndAddend = [&](RelaTy Rela) -> std::pair<Defined *, int64_t> { | ||||
Done Replynit: use shorter variable name for a variable with just two lines of scope. ruiu: nit: use shorter variable name for a variable with just two lines of scope. | |||||
122 | Symbol &Sym = TocSec->getFile<ELFT>()->getRelocTargetSym(Rela); | ||||
123 | return {dyn_cast_or_null<Defined>(&Sym), getAddend<ELFT>(Rela)}; | ||||
MaskRayUnsubmitted Not Done ReplySym as a reference can't be null, so you can use dyn_cast instead of dyn_cast_or_null. MaskRay: `Sym` as a reference can't be null, so you can use `dyn_cast` instead of `dyn_cast_or_null`. | |||||
124 | }; | ||||
125 | | ||||
126 | // The relocations are sorted by offset, and while the most common case is | ||||
Done ReplyYou can write shorter: return {dyn_cast_or_null<Defined>(&IndirectSym), getAddend<ELFT>(Rela)}; grimar: You can write shorter:
```
return {dyn_cast_or_null<Defined>(&IndirectSym), getAddend<ELFT>… | |||||
MaskRayUnsubmitted Not Done Reply
IIRC this is not guaranteed but I think it is fine to lose toc optimization if the input does not have this property. The linear search below for (auto R : llvm::reverse(Relas.slice(0, Index))) { concerns me. Is it possible to add a LastRelaIndex variable in InputSectionBase::relocateAlloc: if (!tryRelaxTocPPC64(Type, Rel, Expr, BufLoc, LastRelaIndex)) and keep it monotonically increasing in getSymAndAddend? If the input doesn't guarantee increasing r_offset, it may lose TOC optimizations for some relocations, but as I said it should be fine. MaskRay: > The relocations are sorted by offset
IIRC this is not guaranteed but I think it is fine to… | |||||
sfertileAuthorUnsubmitted Done Reply
I believe its guaranteed for binutils tools. We also sort the relocations for the .toc section in scanRelocs in case there are other tools which don't produce the relocations in sorted order.
I believe missing toc relocations to be an uncommon thing. As far as I am aware llvm will not place constants into the .toc section. gcc will for a few very specific cases but it is still not very common. xlc is the outlier here as I heard it will do this some what commonly despite there being no need to with the V2 abi. For the objects I found that were missing relocations when compiled with gcc , we either found the relocation we were looking for, or broke out of the search in a few comparisons. If a linear search does become a problem for some pathological inputs we could switch to a binary search but I think doing that initially we would end up pessimaling the common case for something that might not ever naturally occur. sfertile: >> The relocations are sorted by offset
> IIRC this is not guaranteed
I believe its guaranteed… | |||||
MaskRayUnsubmitted Not Done ReplyI was not suggesting a binary search. I suggested to change: for (const Relocation &Rel : Relocations) { // the loop is in relocateAlloc // Offset is increasing for (Index = computed(Rel); J >= 0; J--) // the loop is in PPC64.cpp getSymAndAddend if (Offset == Relas[Index].r_offset) { /* found */ break; } } to Index = 0 for (const Relocation &Rel : Relocations) { // the loop is in relocateAlloc // Offset is increasing for (; Index < Relas.size(); ++Index) // Index is increasing if (Offset == Relas[Index].r_offset) { /* found */ break; } } MaskRay: I was not suggesting a binary search.
I suggested to change:
```
for (const Relocation &Rel… | |||||
MaskRayUnsubmitted Not Done ReplySorry, see below: for (const Relocation &Rel : Relocations) { // the loop is in relocateAlloc // Offset is increasing for (Index = computed(Rel); Index >= 0; Index--) // the loop is in PPC64.cpp getSymAndAddend if (Offset == Relas[Index].r_offset) { /* found */ break; } } to Index = 0 for (const Relocation &Rel : Relocations) { // the loop is in relocateAlloc // Offset is increasing for (; Index < Relas.size(); ++Index) // Index is increasing if (Offset == Relas[Index].r_offset) { /* found */ break; } else if (Offset < Relas[Index].r_offset) break; } MaskRay: Sorry, see below:
```
for (const Relocation &Rel : Relocations) { // the loop is in… | |||||
sfertileAuthorUnsubmitted Not Done ReplyI think I may have misunderstood which relocations you were referring too with the first comment about sort order. Only the relocations that operate on the .toc section are sorted. (Otherwise I'm misunderstanding this proposed change, perhaps we could talk on IRC to clairfy?) Here is my understanding of the proposed look-up: Index = 0 for (const Relocation &Rel : Relocations) { // the loop is in relocateAlloc // Offset is not (guranteed) increasing, Addend is not (typically) increasing. Rel.Sym // This must be .toc if its an indirect. Rel.Addend // The addends will not be in any particular order. // When looking up the symbol we indirect too, we want to find the // relocation that relocates the toc section at offset `Rel.Addend`. Rel.Offset // The offset in the section being relocated. Unrelated to the lookup performed in the .toc section. // Inside the PPC64 target. // Loop over the relocations for the .toc section. These **are** sorted based on offset. for (; Index < Relas.size(); ++Index) // Index is increasing if (Offset == Relas[Index].r_offset) { /* found */ break; } else if (Offset < Relas[Index].r_offset) break; }
sfertile: I think I may have misunderstood which relocations you were referring too with the first… | |||||
127 | // that every .toc entry will have a relocation, it is not guaranteed. For | ||||
128 | // example objects compiled with small code model are likely to have | ||||
129 | // constants placed in the .toc section. Start looking by mapping the offset | ||||
130 | // directly into its corresponding toc entry. | ||||
131 | size_t Index = std::min(Offset / Target->GotEntrySize, Relas.size() - 1); | ||||
132 | if (Offset == Relas[Index].r_offset) | ||||
133 | return SymAndAddend(Relas[Index]); | ||||
134 | | ||||
135 | // If Offset is greater than r_offset on the relocation we looked up we must | ||||
136 | // have less relocations then toc enties and Relas[Index] is the last reloc | ||||
Done ReplyWhy not DefSym->Section->Name != ".toc" ? grimar: Why not `DefSym->Section->Name != ".toc"` ? | |||||
137 | // in the array. In this case we have nothing to relax to. | ||||
Done Replyreturn {}; grimar: `return {};` | |||||
ruiuUnsubmitted Not Done ReplyI think I don't understand why you can't relax if the number of relocations for the .toc is smaller than the number of entires in .toc. I thought that if you can find a relocation that has a specific offset, that's the relocation that you are looking for, and you can read a symbol and an offset from that relocation. I think there's something more about PPC64 ABI that I don't know of. Could you explain? ruiu: I think I don't understand why you can't relax if the number of relocations for the .toc is… | |||||
sfertileAuthorUnsubmitted Not Done ReplyI think the missing piece here is that I am assuming each toc entry has at most 1 relocation. The relocations are R_PPC64_ADDR64 and relocates one full entry each, or we have a constant/value with no relocation. That way a look up should always find an r_offset greater then or equal to Offset on the first look-up, except for when we truncated the index because the one we calculated was outside the array bounds. If we truncated the index and find a r_offset < Offset we can return because the array is sorted by offset. sfertile: I think the missing piece here is that I am assuming each toc entry has at most 1 relocation. | |||||
138 | if (Offset > Relas[Index].r_offset) | ||||
139 | return {}; | ||||
140 | | ||||
Done Replyreturn {}; grimar: `return {};` | |||||
141 | // Walk back looking for a relocation that relocates .toc + Offset. | ||||
142 | for (auto R : llvm::reverse(Relas.slice(0, Index))) { | ||||
143 | if (R.r_offset == Offset) | ||||
144 | return SymAndAddend(R); | ||||
145 | if (R.r_offset < Offset) | ||||
146 | return {}; | ||||
147 | } | ||||
148 | | ||||
149 | // No relocation for the toc entry .toc + Offset. | ||||
150 | return {}; | ||||
151 | } | ||||
152 | | ||||
153 | // Determines the target of a toc-indirection to relax to. Returns the symbol + | ||||
154 | // addend pair if there is a symbol to relax to. | ||||
Done ReplySo maybe you should never reach here if !Config->TocOptimize? case R_PPC64_TOC16_HA: case R_PPC64_TOC16_LO_DS: return Config->TocOptimize ? R_PPC64_RELAX_TOC : R_XXXX; grimar: So maybe you should never reach here if `!Config->TocOptimize`?
Seems you can do something like… | |||||
155 | static std::pair<Defined *, int64_t> relaxTo(Relocation Rel) { | ||||
156 | // If the symbol the relocation refers to is not the .toc section | ||||
Done ReplyRelaxTo.first/RelaxTo.second are a bit hard to follow and read. Lets do: Defined *D; int64_t Addend; std::tie(D, Addend) = relaxTo(Rel); grimar: `RelaxTo.first`/`RelaxTo.second` are a bit hard to follow and read. Lets do:
```
Defined *D… | |||||
157 | // this can't be a toc-indirection. | ||||
158 | Defined *DefSym = dyn_cast<Defined>(Rel.Sym); | ||||
159 | if (!DefSym || !DefSym->isSection() || DefSym->Section->Name != ".toc") | ||||
160 | return {}; | ||||
161 | | ||||
162 | if (Rel.Addend < 0) | ||||
163 | return {}; | ||||
164 | | ||||
165 | auto *TocISB = cast<InputSectionBase>(DefSym->Section); | ||||
166 | // Get the symbol + addend that the toc-indirection refers to. | ||||
167 | return Config->IsLE ? getSymAndAddend<ELF64LE>(TocISB, Rel.Addend) | ||||
168 | : getSymAndAddend<ELF64BE>(TocISB, Rel.Addend); | ||||
169 | } | ||||
170 | | ||||
171 | // Attempts to relax loading a symbols address from the .toc section into | ||||
Done ReplyCan you add a high-level comment as to what optimization this function is supposed to do? ruiu: Can you add a high-level comment as to what optimization this function is supposed to do? | |||||
172 | // calculating the symbols address using an offset relative to the toc pointer. | ||||
173 | // To be able to relax the target symbol must be defined, not preemptible and | ||||
174 | // addressable with a 32-bit signed offset from the toc pointer. | ||||
Not Done ReplyThe title of this revision says "toc-indirect" while here and some other places say "got-indirect". Which term is preferred? (Or maybe they are two different things and I am confused..) MaskRay: The title of this revision says "toc-indirect" while here and some other places say "got… | |||||
Not Done Replygot-indirect is the term used in the ABI and so I have tried to stick mostly to that, especially for anything a user would see like a diagnostic. toc-indirect is a term I made up to describe the way gcc/clang/xlc actually produce a got-indirecton as its a bit different then what I think most would expect. The 2 ways have slightly different input, but the output from the linker is the same. got-indirect -> its up to the linker to allocate a got entry for sym. The got entry is accessed relative to the toc-pointer. addis r3, r2, sym@got@ha ld r3, sym@got@l(r3) lwa r3, r3 vs toc-indirect --> the compiler allocates an entry in the .toc section and puts a relocation for the symbols address into that .toc entry. The toc entry is accessed relative to the toc-pointer. addis r3, r2, .LC0@toc@ha ld r3, .LC0@toc@l(r3) lwa r3, r3 ... .toc .LC0: .tc sym[TC], sym # emits a relocation for sym. Roughly equivalent to .quad sym? All this extra work in looking up the relocation to find the symbol thats being accessed is because the compiler emits the second form rather then the first. In the final binary the .toc sections are either merged into the .got section (bfd/gold) or allocated right after the .got section (lld) and you end up with a got-indirect access. sfertile: got-indirect is the term used in the ABI and so I have tried to stick mostly to that… | |||||
175 | bool elf::tryRelaxTocPPC64(RelType Type, const Relocation &Rel, RelExpr Expr, | ||||
176 | uint8_t *BufLoc) { | ||||
177 | assert(Expr == R_PPC64_RELAX_TOC && | ||||
178 | "unexpected RelExpr for got-indirect to toc-relative relaxation"); | ||||
179 | assert(Config->TocOptimize && | ||||
180 | "tryRelaxTocPPC64 should only be called when --toc-optimize is enabled"); | ||||
181 | | ||||
182 | Defined *D; | ||||
183 | int64_t Addend; | ||||
184 | std::tie(D, Addend) = relaxTo(Rel); | ||||
185 | | ||||
186 | // If there is no defined symbol or if the defined symbol is preemptible then | ||||
187 | // the relocation cannot be relaxed. | ||||
188 | if (!D || D->IsPreemptible) | ||||
189 | return false; | ||||
190 | | ||||
191 | uint64_t SymVA = D->getVA(Addend); | ||||
192 | // Because we only have the 2 instructions of the got-indirect access sequence | ||||
193 | // to rewrite, we can only relax if the symbol definition is within 32 bits of | ||||
194 | // the TOC base-pointer. For medium code model this is guaranteed but in the | ||||
195 | // large code model parts of the data segment will be too far away to relax. | ||||
196 | if (!isInt<32>(SymVA - getPPC64TocBase())) | ||||
197 | return false; | ||||
198 | | ||||
199 | // Safe to relax, let the target callback perform the actual relaxation. | ||||
200 | // Note that we use the offset between the symbols VA and the .got VA as the | ||||
201 | // relocation value since relocateOne will perform the adjustment by the TOC | ||||
202 | // bias. | ||||
203 | Target->relaxGot(BufLoc, Type, SymVA - In.Got->getVA()); | ||||
204 | return true; | ||||
205 | } | ||||
206 | | ||||
110 | namespace { | 207 | namespace { | ||
111 | class PPC64 final : public TargetInfo { | 208 | class PPC64 final : public TargetInfo { | ||
112 | public: | 209 | public: | ||
113 | PPC64(); | 210 | PPC64(); | ||
114 | uint32_t calcEFlags() const override; | 211 | uint32_t calcEFlags() const override; | ||
115 | RelExpr getRelExpr(RelType Type, const Symbol &S, | 212 | RelExpr getRelExpr(RelType Type, const Symbol &S, | ||
116 | const uint8_t *Loc) const override; | 213 | const uint8_t *Loc) const override; | ||
117 | void writePltHeader(uint8_t *Buf) const override; | 214 | void writePltHeader(uint8_t *Buf) const override; | ||
118 | void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, | 215 | void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, | ||
119 | int32_t Index, unsigned RelOff) const override; | 216 | int32_t Index, unsigned RelOff) const override; | ||
120 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; | 217 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; | ||
121 | void writeGotHeader(uint8_t *Buf) const override; | 218 | void writeGotHeader(uint8_t *Buf) const override; | ||
122 | bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, | 219 | bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, | ||
123 | uint64_t BranchAddr, const Symbol &S) const override; | 220 | uint64_t BranchAddr, const Symbol &S) const override; | ||
124 | bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; | 221 | bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; | ||
125 | RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, | 222 | RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, | ||
126 | RelExpr Expr) const override; | 223 | RelExpr Expr) const override; | ||
224 | void relaxGot(uint8_t *Loc, RelType Type, uint64_t Val) const override; | ||||
127 | void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override; | 225 | void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override; | ||
128 | void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; | 226 | void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; | ||
129 | void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; | 227 | void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; | ||
130 | void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; | 228 | void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; | ||
131 | 229 | | |||
132 | bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, | 230 | bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, | ||
133 | uint8_t StOther) const override; | 231 | uint8_t StOther) const override; | ||
134 | }; | 232 | }; | ||
▲ Show 20 Lines • Show All 120 Lines • ▼ Show 20 Line(s) | 351 | for (InputFile *F : ObjectFiles) { | |||
255 | if (Flag == 1) | 353 | if (Flag == 1) | ||
256 | error(toString(F) + ": ABI version 1 is not supported"); | 354 | error(toString(F) + ": ABI version 1 is not supported"); | ||
257 | else if (Flag > 2) | 355 | else if (Flag > 2) | ||
258 | error(toString(F) + ": unrecognized e_flags: " + Twine(Flag)); | 356 | error(toString(F) + ": unrecognized e_flags: " + Twine(Flag)); | ||
259 | } | 357 | } | ||
260 | return 2; | 358 | return 2; | ||
261 | } | 359 | } | ||
262 | 360 | | |||
361 | void PPC64::relaxGot(uint8_t *Loc, RelType Type, uint64_t Val) const { | ||||
362 | switch (Type) { | ||||
363 | case R_PPC64_TOC16_HA: | ||||
364 | relocateOne(Loc, Type, Val); | ||||
365 | break; | ||||
366 | case R_PPC64_TOC16_LO_DS: { | ||||
367 | // rewrite the instuction from a load to an addi. | ||||
368 | uint32_t Instr = readInstrFromHalf16(Loc); | ||||
369 | if (getPrimaryOpCode(Instr) != LD) | ||||
Done ReplyInstead of 58, we can use the enum DFormOpcd which has LD defined to 58. syzaara: Instead of 58, we can use the enum DFormOpcd which has LD defined to 58. | |||||
370 | error("expected a 'ld' for got-indirect to toc-relative relaxing"); | ||||
371 | writeInstrFromHalf16(Loc, (Instr & 0x03FFFFFF) | 0x38000000); | ||||
Done ReplyExpeceted -> Expected syzaara: Expeceted -> Expected | |||||
Done ReplyError messages should start with a lowercase letter. I think you should use error() instead of llvm_unreachable() because this condition can be triggered by a user. llvm_unreachable should be used only to report an internal error or a bug. ruiu: Error messages should start with a lowercase letter.
I think you should use `error()` instead… | |||||
372 | relocateOne(Loc, R_PPC64_TOC16_LO, Val); | ||||
Done ReplyInstr &= 0x03FFFFFF; MaskRay: Instr &= 0x03FFFFFF; | |||||
373 | break; | ||||
374 | } | ||||
Done ReplyI think Instr = (Instr & 0x3FFFFFF) | 0x38000000; is a bit more straightforward. Or, writeInstrFromHalf16(Loc, (Instr & 0x3FFFFFF) | 0x38000000); is perhaps better. ruiu: I think `Instr = (Instr & 0x3FFFFFF) | 0x38000000;` is a bit more straightforward.
Or… | |||||
375 | default: | ||||
376 | error( | ||||
Done ReplyThis is an unusual formatting style in lld. Please put break before }. ruiu: This is an unusual formatting style in lld. Please put `break` before `}`. | |||||
377 | "unexpected relocation type for got-indirect to toc-relative relaxing"); | ||||
378 | } | ||||
379 | } | ||||
Done ReplyU -> u ruiu: U -> u | |||||
380 | | ||||
263 | void PPC64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { | 381 | void PPC64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { | ||
264 | // Reference: 3.7.4.2 of the 64-bit ELF V2 abi supplement. | 382 | // Reference: 3.7.4.2 of the 64-bit ELF V2 abi supplement. | ||
265 | // The general dynamic code sequence for a global `x` will look like: | 383 | // The general dynamic code sequence for a global `x` will look like: | ||
266 | // Instruction Relocation Symbol | 384 | // Instruction Relocation Symbol | ||
267 | // addis r3, r2, x@got@tlsgd@ha R_PPC64_GOT_TLSGD16_HA x | 385 | // addis r3, r2, x@got@tlsgd@ha R_PPC64_GOT_TLSGD16_HA x | ||
268 | // addi r3, r3, x@got@tlsgd@l R_PPC64_GOT_TLSGD16_LO x | 386 | // addi r3, r3, x@got@tlsgd@l R_PPC64_GOT_TLSGD16_LO x | ||
269 | // bl __tls_get_addr(x@tlsgd) R_PPC64_TLSGD x | 387 | // bl __tls_get_addr(x@tlsgd) R_PPC64_TLSGD x | ||
270 | // R_PPC64_REL24 __tls_get_addr | 388 | // R_PPC64_REL24 __tls_get_addr | ||
▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Line(s) | 538 | RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S, | |||
424 | case R_PPC64_GOT16_DS: | 542 | case R_PPC64_GOT16_DS: | ||
425 | case R_PPC64_GOT16_HA: | 543 | case R_PPC64_GOT16_HA: | ||
426 | case R_PPC64_GOT16_HI: | 544 | case R_PPC64_GOT16_HI: | ||
427 | case R_PPC64_GOT16_LO: | 545 | case R_PPC64_GOT16_LO: | ||
428 | case R_PPC64_GOT16_LO_DS: | 546 | case R_PPC64_GOT16_LO_DS: | ||
429 | return R_GOT_OFF; | 547 | return R_GOT_OFF; | ||
430 | case R_PPC64_TOC16: | 548 | case R_PPC64_TOC16: | ||
431 | case R_PPC64_TOC16_DS: | 549 | case R_PPC64_TOC16_DS: | ||
432 | case R_PPC64_TOC16_HA: | | |||
433 | case R_PPC64_TOC16_HI: | 550 | case R_PPC64_TOC16_HI: | ||
434 | case R_PPC64_TOC16_LO: | 551 | case R_PPC64_TOC16_LO: | ||
435 | case R_PPC64_TOC16_LO_DS: | | |||
436 | return R_GOTREL; | 552 | return R_GOTREL; | ||
553 | case R_PPC64_TOC16_HA: | ||||
554 | case R_PPC64_TOC16_LO_DS: | ||||
555 | return Config->TocOptimize ? R_PPC64_RELAX_TOC : R_GOTREL; | ||||
437 | case R_PPC64_TOC: | 556 | case R_PPC64_TOC: | ||
438 | return R_PPC_TOC; | 557 | return R_PPC_TOC; | ||
439 | case R_PPC64_REL14: | 558 | case R_PPC64_REL14: | ||
440 | case R_PPC64_REL24: | 559 | case R_PPC64_REL24: | ||
441 | return R_PPC_CALL_PLT; | 560 | return R_PPC_CALL_PLT; | ||
442 | case R_PPC64_REL16_LO: | 561 | case R_PPC64_REL16_LO: | ||
443 | case R_PPC64_REL16_HA: | 562 | case R_PPC64_REL16_HA: | ||
444 | case R_PPC64_REL32: | 563 | case R_PPC64_REL32: | ||
▲ Show 20 Lines • Show All 495 Lines • Show Last 20 Lines |
Warnings and error messages should start from the lowercase.