Lines Matching +full:power +full:- +full:off +full:- +full:time +full:- +full:sec
1 //===- Chunks.cpp ---------------------------------------------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
38 setRelocs(file->getCOFFObj()->getRelocations(header));
43 if (Expected<StringRef> e = file->getCOFFObj()->getSectionName(header))
49 setAlignment(header->getAlignment());
51 hasData = !(header->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA);
54 // enabled, treat non-comdat sections as roots. Generally optimized object
55 // files will be built with -ffunction-sections or /Gy, so most things worth
58 live = !file->ctx.config.doGC || !isCOMDAT();
76 // sections have section-relative relocations against absolute symbols.
77 static bool checkSecRel(const SectionChunk *sec, OutputSection *os) {
80 if (sec->isCodeView())
86 static void applySecRel(const SectionChunk *sec, uint8_t *off,
88 if (!checkSecRel(sec, os))
90 uint64_t secRel = s - os->getRVA();
92 error("overflow in SECREL relocation in section: " + sec->getSectionName());
95 add32(off, secRel);
98 static void applySecIdx(uint8_t *off, OutputSection *os,
108 add16(off, os->sectionIndex);
110 add16(off, numOutputSections + 1);
113 void SectionChunk::applyRelX64(uint8_t *off, uint16_t type, OutputSection *os,
118 add32(off, s + imageBase);
121 add64(off, s + imageBase);
123 case IMAGE_REL_AMD64_ADDR32NB: add32(off, s); break;
124 case IMAGE_REL_AMD64_REL32: add32(off, s - p - 4); break;
125 case IMAGE_REL_AMD64_REL32_1: add32(off, s - p - 5); break;
126 case IMAGE_REL_AMD64_REL32_2: add32(off, s - p - 6); break;
127 case IMAGE_REL_AMD64_REL32_3: add32(off, s - p - 7); break;
128 case IMAGE_REL_AMD64_REL32_4: add32(off, s - p - 8); break;
129 case IMAGE_REL_AMD64_REL32_5: add32(off, s - p - 9); break;
131 applySecIdx(off, os, file->ctx.outputSections.size());
133 case IMAGE_REL_AMD64_SECREL: applySecRel(this, off, os, s); break;
140 void SectionChunk::applyRelX86(uint8_t *off, uint16_t type, OutputSection *os,
146 add32(off, s + imageBase);
148 case IMAGE_REL_I386_DIR32NB: add32(off, s); break;
149 case IMAGE_REL_I386_REL32: add32(off, s - p - 4); break;
151 applySecIdx(off, os, file->ctx.outputSections.size());
153 case IMAGE_REL_I386_SECREL: applySecRel(this, off, os, s); break;
160 static void applyMOV(uint8_t *off, uint16_t v) {
161 write16le(off, (read16le(off) & 0xfbf0) | ((v & 0x800) >> 1) | ((v >> 12) & 0xf));
162 write16le(off + 2, (read16le(off + 2) & 0x8f00) | ((v & 0x700) << 4) | (v & 0xff));
165 static uint16_t readMOV(uint8_t *off, bool movt) {
166 uint16_t op1 = read16le(off);
170 uint16_t op2 = read16le(off + 2);
178 void applyMOV32T(uint8_t *off, uint32_t v) {
179 uint16_t immW = readMOV(off, false); // read MOVW operand
180 uint16_t immT = readMOV(off + 4, true); // read MOVT operand
183 applyMOV(off, v); // set MOVW operand
184 applyMOV(off + 4, v >> 16); // set MOVT operand
187 static void applyBranch20T(uint8_t *off, int32_t v) {
193 or16(off, (s << 10) | ((v >> 12) & 0x3f));
194 or16(off + 2, (j1 << 13) | (j2 << 11) | ((v >> 1) & 0x7ff));
197 void applyBranch24T(uint8_t *off, int32_t v) {
203 or16(off, (s << 10) | ((v >> 12) & 0x3ff));
205 write16le(off + 2, (read16le(off + 2) & 0xd000) | (j1 << 13) | (j2 << 11) | ((v >> 1) & 0x7ff));
208 void SectionChunk::applyRelARM(uint8_t *off, uint16_t type, OutputSection *os,
213 if (os && (os->header.Characteristics & IMAGE_SCN_MEM_EXECUTE))
217 add32(off, sx + imageBase);
219 case IMAGE_REL_ARM_ADDR32NB: add32(off, sx); break;
221 applyMOV32T(off, sx + imageBase);
223 case IMAGE_REL_ARM_BRANCH20T: applyBranch20T(off, sx - p - 4); break;
224 case IMAGE_REL_ARM_BRANCH24T: applyBranch24T(off, sx - p - 4); break;
225 case IMAGE_REL_ARM_BLX23T: applyBranch24T(off, sx - p - 4); break;
227 applySecIdx(off, os, file->ctx.outputSections.size());
229 case IMAGE_REL_ARM_SECREL: applySecRel(this, off, os, s); break;
230 case IMAGE_REL_ARM_REL32: add32(off, sx - p - 4); break;
240 void applyArm64Addr(uint8_t *off, uint64_t s, uint64_t p, int shift) {
241 uint32_t orig = read32le(off);
245 imm = (s >> shift) - (p >> shift);
249 write32le(off, (orig & ~mask) | immLo | immHi);
255 void applyArm64Imm(uint8_t *off, uint64_t imm, uint32_t rangeLimit) {
256 uint32_t orig = read32le(off);
259 write32le(off, orig | ((imm & (0xFFF >> rangeLimit)) << 10));
270 static void applyArm64Ldr(uint8_t *off, uint64_t imm) {
271 uint32_t orig = read32le(off);
277 if ((imm & ((1 << size) - 1)) != 0)
279 applyArm64Imm(off, imm >> size, size);
282 static void applySecRelLow12A(const SectionChunk *sec, uint8_t *off,
284 if (checkSecRel(sec, os))
285 applyArm64Imm(off, (s - os->getRVA()) & 0xfff, 0);
288 static void applySecRelHigh12A(const SectionChunk *sec, uint8_t *off,
290 if (!checkSecRel(sec, os))
292 uint64_t secRel = (s - os->getRVA()) >> 12;
295 sec->getSectionName());
298 applyArm64Imm(off, secRel & 0xfff, 0);
301 static void applySecRelLdr(const SectionChunk *sec, uint8_t *off,
303 if (checkSecRel(sec, os))
304 applyArm64Ldr(off, (s - os->getRVA()) & 0xfff);
307 void applyArm64Branch26(uint8_t *off, int64_t v) {
310 or32(off, (v & 0x0FFFFFFC) >> 2);
313 static void applyArm64Branch19(uint8_t *off, int64_t v) {
316 or32(off, (v & 0x001FFFFC) << 3);
319 static void applyArm64Branch14(uint8_t *off, int64_t v) {
322 or32(off, (v & 0x0000FFFC) << 3);
325 void SectionChunk::applyRelARM64(uint8_t *off, uint16_t type, OutputSection *os,
329 case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(off, s, p, 12); break;
330 case IMAGE_REL_ARM64_REL21: applyArm64Addr(off, s, p, 0); break;
331 case IMAGE_REL_ARM64_PAGEOFFSET_12A: applyArm64Imm(off, s & 0xfff, 0); break;
332 case IMAGE_REL_ARM64_PAGEOFFSET_12L: applyArm64Ldr(off, s & 0xfff); break;
333 case IMAGE_REL_ARM64_BRANCH26: applyArm64Branch26(off, s - p); break;
334 case IMAGE_REL_ARM64_BRANCH19: applyArm64Branch19(off, s - p); break;
335 case IMAGE_REL_ARM64_BRANCH14: applyArm64Branch14(off, s - p); break;
337 add32(off, s + imageBase);
339 case IMAGE_REL_ARM64_ADDR32NB: add32(off, s); break;
341 add64(off, s + imageBase);
343 case IMAGE_REL_ARM64_SECREL: applySecRel(this, off, os, s); break;
344 case IMAGE_REL_ARM64_SECREL_LOW12A: applySecRelLow12A(this, off, os, s); break;
345 case IMAGE_REL_ARM64_SECREL_HIGH12A: applySecRelHigh12A(this, off, os, s); break;
346 case IMAGE_REL_ARM64_SECREL_LOW12L: applySecRelLdr(this, off, os, s); break;
348 applySecIdx(off, os, file->ctx.outputSections.size());
350 case IMAGE_REL_ARM64_REL32: add32(off, s - p - 4); break;
365 if (fromChunk->isCodeView() || fromChunk->isDWARF() || isMinGW)
370 ObjFile *file = fromChunk->file;
373 name = sym->getName();
376 check(file->getCOFFObj()->getSymbol(rel.SymbolTableIndex));
377 name = check(file->getCOFFObj()->getSymbolName(coffSym));
418 write32le(buf - sizeof(uint32_t), entryThunk->getRVA() - rva + 1);
421 void SectionChunk::applyRelocation(uint8_t *off,
423 auto *sym = dyn_cast_or_null<Defined>(file->getSymbol(rel.SymbolTableIndex));
428 Chunk *c = sym ? sym->getChunk() : nullptr;
429 OutputSection *os = c ? file->ctx.getOutputSection(c) : nullptr;
437 maybeReportRelocationToDiscarded(this, sym, rel, file->ctx.config.mingw);
441 uint64_t s = sym->getRVA();
445 uint64_t imageBase = file->ctx.config.imageBase;
448 applyRelX64(off, rel.Type, os, s, p, imageBase);
451 applyRelX86(off, rel.Type, os, s, p, imageBase);
454 applyRelARM(off, rel.Type, os, s, p, imageBase);
457 applyRelARM64(off, rel.Type, os, s, p, imageBase);
471 warn("some relocations in " + file->getName() + " are not sorted");
481 void SectionChunk::writeAndRelocateSubsection(ArrayRef<uint8_t> sec,
485 assert(!subsec.empty() && !sec.empty());
486 assert(sec.begin() <= subsec.begin() && subsec.end() <= sec.end() &&
488 size_t vaBegin = std::distance(sec.begin(), subsec.begin());
489 size_t vaEnd = std::distance(sec.begin(), subsec.end());
500 applyRelocation(&buf[rel.VirtualAddress - vaBegin], rel);
507 assert(child->assocChildren == nullptr &&
511 for (; next != nullptr; prev = next, next = next->assocChildren) {
512 if (next->getSectionName() <= child->getSectionName())
517 assert(prev->assocChildren == next);
518 prev->assocChildren = child;
519 child->assocChildren = next;
550 // Windows-specific.
552 // fixed by the loader if load-time relocation is needed.
559 Symbol *target = file->getSymbol(rel.SymbolTableIndex);
562 res->emplace_back(rva + rel.VirtualAddress, ty);
588 // *(base + .target) += *(base + .sym) - (base + .sym)
654 dyn_cast_or_null<Defined>(file->getSymbol(rel.SymbolTableIndex));
655 if (!target || !target->isRuntimePseudoReloc)
662 if (!target->getChunk())
665 getRuntimePseudoRelocSize(rel.Type, file->ctx.config.machine);
667 error("unable to automatically import from " + target->getName() +
669 file->getCOFFObj()->getRelocationTypeName(rel.Type) + " in " +
673 int addressSizeInBits = file->ctx.config.is64() ? 64 : 32;
676 "symbol " + target->getName() + " is too narrow (only " +
687 return header->Characteristics & IMAGE_SCN_LNK_COMDAT;
691 // Removed by dead-stripping. If it's removed by ICF, ICF already
694 log("Discarded " + sym->getName());
699 return sym->getName();
705 cantFail(file->getCOFFObj()->getSectionContents(header, a));
741 if (c->getSectionName() == name)
747 p2Align = std::max(p2Align, other->p2Align);
748 other->repl = repl;
749 other->live = false;
755 SectionRef s(r, file->getCOFFObj());
761 // than 32 bytes naturally, i.e. round the size up to the next power of two.
780 // should be 16-byte aligned. MSVC linker does this too.
787 write32le(buf + 2, impSymbol->getRVA() - rva - getSize());
791 res->emplace_back(getRVA() + 2, ctx.config.machine);
797 write32le(buf + 2, impSymbol->getRVA() + ctx.config.imageBase);
801 res->emplace_back(getRVA(), IMAGE_REL_BASED_ARM_MOV32T);
807 applyMOV32T(buf, impSymbol->getRVA() + ctx.config.imageBase);
811 int64_t off = impSymbol->getRVA() & 0xfff;
813 applyArm64Addr(buf, impSymbol->getRVA(), rva, 12);
814 applyArm64Ldr(buf + 4, off);
817 // A Thumb2, PIC, non-interworking range extension thunk.
819 0x40, 0xf2, 0x00, 0x0c, // P: movw ip,:lower16:S - (P + (L1-P) + 4)
820 0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P) + 4)
832 uint64_t offset = target->getRVA() - rva - 12;
838 // +/- 4 GB, which is enough for any PE-COFF.
854 applyArm64Addr(buf + 0, target->getRVA(), rva, 12);
855 applyArm64Imm(buf + 4, target->getRVA() & 0xfff, 0);
864 res->emplace_back(getRVA(), ctx.config.machine);
871 write64le(buf, sym->getRVA() + ctx.config.imageBase);
873 write32le(buf, sym->getRVA() + ctx.config.imageBase);
881 begin[cnt++] = co.inputChunk->getRVA() + co.offset;
884 "RVA tables should be de-duplicated");
897 flag.rva = sym.inputChunk->getRVA() + sym.offset;
905 "RVA tables should be de-duplicated");
916 uint32_t start = entry.first->getRVA();
918 table[i].Length = entry.last->getRVA() + entry.last->getSize() - start;
943 table[idx + 0] = rpr.sym->getRVA();
944 table[idx + 1] = rpr.target->getRVA() + rpr.targetOffset;
950 // Windows-specific. This class represents a block in .reloc section.
959 // base address> - <desired base address> to each offset that is
976 // 0x00000 -- page address (4 bytes)
977 // 16 -- size of this block (4 bytes)
978 // 0xA030 -- entries (2 bytes each)
982 // 0x20000 -- page address (4 bytes)
983 // 12 -- size of this block (4 bytes)
984 // 0xA004 -- entries (2 bytes each)
992 data.resize(alignTo((end - begin) * 2 + 8, 4));
998 write16le(p, (i->type << 12) | (i->rva - page));
1026 assert(isPowerOf2_32(c->getAlignment()));
1027 uint8_t p2Align = llvm::Log2_32(c->getAlignment());
1031 mc = make<MergeChunk>(c->getAlignment());
1032 mc->sections.push_back(c);
1038 if (c->live)
1039 builder.add(toStringRef(c->getContents()));
1046 if (!c->live)
1048 size_t off = builder.getOffset(toStringRef(c->getContents()));
1049 c->setRVA(rva + off);