Coverage Report

Created: 2025-07-18 06:59

/src/keystone/llvm/lib/MC/MCFragment.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- lib/MC/MCFragment.cpp - Assembler Fragment Implementation ----------===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
10
#include "llvm/MC/MCFragment.h"
11
#include "llvm/ADT/StringExtras.h"
12
#include "llvm/ADT/Twine.h"
13
#include "llvm/MC/MCAsmBackend.h"
14
#include "llvm/MC/MCAsmInfo.h"
15
#include "llvm/MC/MCAsmLayout.h"
16
#include "llvm/MC/MCContext.h"
17
#include "llvm/MC/MCDwarf.h"
18
#include "llvm/MC/MCExpr.h"
19
#include "llvm/MC/MCFixupKindInfo.h"
20
#include "llvm/MC/MCSection.h"
21
#include "llvm/MC/MCSectionELF.h"
22
#include "llvm/MC/MCSymbol.h"
23
#include "llvm/MC/MCValue.h"
24
#include "llvm/Support/ErrorHandling.h"
25
#include "llvm/Support/LEB128.h"
26
#include "llvm/Support/TargetRegistry.h"
27
#include "llvm/Support/raw_ostream.h"
28
#include <tuple>
29
using namespace llvm_ks;
30
31
MCAsmLayout::MCAsmLayout(MCAssembler &Asm)
32
57.9k
  : Assembler(Asm), LastValidFragment()
33
57.9k
 {
34
  // Compute the section layout order. Virtual sections must go last.
35
57.9k
  for (MCSection &Sec : Asm)
36
59.9k
    if (!Sec.isVirtualSection())
37
59.8k
      SectionOrder.push_back(&Sec);
38
57.9k
  for (MCSection &Sec : Asm)
39
59.9k
    if (Sec.isVirtualSection())
40
175
      SectionOrder.push_back(&Sec);
41
57.9k
}
42
43
2.45M
bool MCAsmLayout::isFragmentValid(const MCFragment *F) const {
44
2.45M
  const MCSection *Sec = F->getParent();
45
2.45M
  const MCFragment *LastValid = LastValidFragment.lookup(Sec);
46
2.45M
  if (!LastValid)
47
120k
    return false;
48
2.33M
  assert(LastValid->getParent() == Sec);
49
2.33M
  return F->getLayoutOrder() <= LastValid->getLayoutOrder();
50
2.33M
}
51
52
529
void MCAsmLayout::invalidateFragmentsFrom(MCFragment *F) {
53
  // If this fragment wasn't already valid, we don't need to do anything.
54
529
  if (!isFragmentValid(F))
55
2
    return;
56
57
  // Otherwise, reset the last valid fragment to the previous fragment
58
  // (if this is the first fragment, it will be NULL).
59
527
  LastValidFragment[F->getParent()] = F->getPrevNode();
60
527
}
61
62
bool MCAsmLayout::ensureValid(const MCFragment *F) const
63
1.05M
{
64
1.05M
  MCSection *Sec = F->getParent();
65
1.05M
  MCSection::iterator I;
66
1.05M
  if (MCFragment *Cur = LastValidFragment[Sec])
67
999k
    I = ++MCSection::iterator(Cur);
68
60.3k
  else
69
60.3k
    I = Sec->begin();
70
71
  // Advance the layout position until the fragment is valid.
72
1.51M
  while (!isFragmentValid(F)) {
73
    //assert(I != Sec->end() && "Layout bookkeeping error");
74
507k
    if (I == Sec->end())
75
10.6k
        return false;
76
496k
    if (const_cast<MCAsmLayout *>(this)->layoutFragment(&*I))
77
38.0k
        return false;
78
458k
    ++I;
79
458k
  }
80
81
1.01M
  return true;
82
1.05M
}
83
84
uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F, bool &valid) const
85
1.05M
{
86
1.05M
  valid = true;
87
1.05M
  if (!ensureValid(F)) {
88
48.7k
      valid = false;
89
48.7k
      return 0;
90
48.7k
  }
91
  //assert(F->Offset != ~UINT64_C(0) && "Address not set!");
92
1.01M
  if (F->Offset == ~UINT64_C(0)) {
93
229
      valid = false;
94
229
      return 0;
95
229
  }
96
97
1.01M
  return F->Offset;
98
1.01M
}
99
100
// Simple getSymbolOffset helper for the non-varibale case.
101
static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbol &S,
102
                           bool ReportError, uint64_t &Val)
103
301k
{
104
301k
  if (!S.getFragment()) {
105
7.19k
    if (ReportError)
106
0
      report_fatal_error("unable to evaluate offset to undefined symbol '" +
107
0
                         S.getName() + "'");
108
7.19k
    return false;
109
7.19k
  }
110
111
294k
  bool valid;
112
294k
  Val = Layout.getFragmentOffset(S.getFragment(), valid) + S.getOffset();
113
114
294k
  return valid;
115
301k
}
116
117
static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, const MCSymbol &S,
118
                                bool ReportError, uint64_t &Val, bool &valid)
119
303k
{
120
303k
  valid = true;
121
303k
  if (!S.isVariable())
122
279k
    return getLabelOffset(Layout, S, ReportError, Val);
123
124
  // If SD is a variable, evaluate it.
125
24.1k
  MCValue Target;
126
24.1k
  if (!S.getVariableValue()->evaluateAsValue(Target, Layout)) {
127
    //report_fatal_error("unable to evaluate offset for variable '" +
128
    //                   S.getName() + "'");
129
2.12k
    valid = false;
130
2.12k
    return false;
131
2.12k
  }
132
133
22.0k
  uint64_t Offset = Target.getConstant();
134
135
22.0k
  const MCSymbolRefExpr *A = Target.getSymA();
136
22.0k
  if (A) {
137
17.7k
    uint64_t ValA;
138
17.7k
    if (!getLabelOffset(Layout, A->getSymbol(), ReportError, ValA))
139
3.54k
      return false;
140
14.1k
    Offset += ValA;
141
14.1k
  }
142
143
18.5k
  const MCSymbolRefExpr *B = Target.getSymB();
144
18.5k
  if (B) {
145
4.35k
    uint64_t ValB;
146
4.35k
    if (!getLabelOffset(Layout, B->getSymbol(), ReportError, ValB))
147
415
      return false;
148
3.93k
    Offset -= ValB;
149
3.93k
  }
150
151
18.0k
  Val = Offset;
152
18.0k
  return true;
153
18.5k
}
154
155
bool MCAsmLayout::getSymbolOffset(const MCSymbol &S, uint64_t &Val, bool &valid) const
156
19.9k
{
157
19.9k
  return getSymbolOffsetImpl(*this, S, false, Val, valid);
158
19.9k
}
159
160
uint64_t MCAsmLayout::getSymbolOffset(const MCSymbol &S, bool &valid) const
161
283k
{
162
283k
  uint64_t Val;
163
283k
  getSymbolOffsetImpl(*this, S, true, Val, valid);
164
283k
  return Val;
165
283k
}
166
167
0
const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const {
168
0
  if (!Symbol.isVariable())
169
0
    return &Symbol;
170
171
0
  const MCExpr *Expr = Symbol.getVariableValue();
172
0
  MCValue Value;
173
0
  if (!Expr->evaluateAsValue(Value, *this)) {
174
0
    Assembler.getContext().reportError(
175
0
        SMLoc(), "expression could not be evaluated");
176
0
    return nullptr;
177
0
  }
178
179
0
  const MCSymbolRefExpr *RefB = Value.getSymB();
180
0
  if (RefB) {
181
0
    Assembler.getContext().reportError(
182
0
        SMLoc(), Twine("symbol '") + RefB->getSymbol().getName() +
183
0
                     "' could not be evaluated in a subtraction expression");
184
0
    return nullptr;
185
0
  }
186
187
0
  const MCSymbolRefExpr *A = Value.getSymA();
188
0
  if (!A)
189
0
    return nullptr;
190
191
0
  const MCSymbol &ASym = A->getSymbol();
192
0
  const MCAssembler &Asm = getAssembler();
193
0
  if (ASym.isCommon()) {
194
    // FIXME: we should probably add a SMLoc to MCExpr.
195
0
    Asm.getContext().reportError(SMLoc(),
196
0
                                 "Common symbol '" + ASym.getName() +
197
0
                                     "' cannot be used in assignment expr");
198
0
    return nullptr;
199
0
  }
200
201
0
  return &ASym;
202
0
}
203
204
uint64_t MCAsmLayout::getSectionAddressSize(const MCSection *Sec) const
205
0
{
206
  // The size is the last fragment's end offset.
207
0
  const MCFragment &F = Sec->getFragmentList().back();
208
0
  bool valid, valid2;
209
0
  return getFragmentOffset(&F, valid2) + getAssembler().computeFragmentSize(*this, F, valid);
210
0
}
211
212
174
uint64_t MCAsmLayout::getSectionFileSize(const MCSection *Sec) const {
213
  // Virtual sections have no file size.
214
174
  if (Sec->isVirtualSection())
215
174
    return 0;
216
217
  // Otherwise, the file size is the same as the address space size.
218
0
  return getSectionAddressSize(Sec);
219
174
}
220
221
uint64_t llvm_ks::computeBundlePadding(const MCAssembler &Assembler,
222
                                    const MCFragment *F,
223
0
                                    uint64_t FOffset, uint64_t FSize) {
224
0
  uint64_t BundleSize = Assembler.getBundleAlignSize();
225
0
  assert(BundleSize > 0 &&
226
0
         "computeBundlePadding should only be called if bundling is enabled");
227
0
  uint64_t BundleMask = BundleSize - 1;
228
0
  uint64_t OffsetInBundle = FOffset & BundleMask;
229
0
  uint64_t EndOfFragment = OffsetInBundle + FSize;
230
231
  // There are two kinds of bundling restrictions:
232
  //
233
  // 1) For alignToBundleEnd(), add padding to ensure that the fragment will
234
  //    *end* on a bundle boundary.
235
  // 2) Otherwise, check if the fragment would cross a bundle boundary. If it
236
  //    would, add padding until the end of the bundle so that the fragment
237
  //    will start in a new one.
238
0
  if (F->alignToBundleEnd()) {
239
    // Three possibilities here:
240
    //
241
    // A) The fragment just happens to end at a bundle boundary, so we're good.
242
    // B) The fragment ends before the current bundle boundary: pad it just
243
    //    enough to reach the boundary.
244
    // C) The fragment ends after the current bundle boundary: pad it until it
245
    //    reaches the end of the next bundle boundary.
246
    //
247
    // Note: this code could be made shorter with some modulo trickery, but it's
248
    // intentionally kept in its more explicit form for simplicity.
249
0
    if (EndOfFragment == BundleSize)
250
0
      return 0;
251
0
    else if (EndOfFragment < BundleSize)
252
0
      return BundleSize - EndOfFragment;
253
0
    else { // EndOfFragment > BundleSize
254
0
      return 2 * BundleSize - EndOfFragment;
255
0
    }
256
0
  } else if (OffsetInBundle > 0 && EndOfFragment > BundleSize)
257
0
    return BundleSize - OffsetInBundle;
258
0
  else
259
0
    return 0;
260
0
}
261
262
/* *** */
263
264
648k
void ilist_node_traits<MCFragment>::deleteNode(MCFragment *V) {
265
648k
  V->destroy();
266
648k
}
267
268
135k
MCFragment::MCFragment() : Kind(FragmentType(~0)), HasInstructions(false),
269
135k
                           AlignToBundleEnd(false), BundlePadding(0) {
270
135k
}
271
272
6.55M
MCFragment::~MCFragment() { }
273
274
MCFragment::MCFragment(FragmentType Kind, bool HasInstructions,
275
                       uint8_t BundlePadding, MCSection *Parent)
276
6.41M
    : Kind(Kind), HasInstructions(HasInstructions), AlignToBundleEnd(false),
277
6.41M
      BundlePadding(BundlePadding), Parent(Parent), Atom(nullptr),
278
6.41M
      Offset(~UINT64_C(0)) {
279
6.41M
  if (Parent && !isDummy())
280
0
    Parent->getFragmentList().push_back(this);
281
6.41M
}
282
283
648k
void MCFragment::destroy() {
284
  // First check if we are the sentinal.
285
648k
  if (Kind == FragmentType(~0)) {
286
0
    delete this;
287
0
    return;
288
0
  }
289
290
648k
  switch (Kind) {
291
97.5k
    case FT_Align:
292
97.5k
      delete cast<MCAlignFragment>(this);
293
97.5k
      return;
294
140k
    case FT_Data:
295
140k
      delete cast<MCDataFragment>(this);
296
140k
      return;
297
0
    case FT_CompactEncodedInst:
298
0
      delete cast<MCCompactEncodedInstFragment>(this);
299
0
      return;
300
47.3k
    case FT_Fill:
301
47.3k
      delete cast<MCFillFragment>(this);
302
47.3k
      return;
303
32.7k
    case FT_Relaxable:
304
32.7k
      delete cast<MCRelaxableFragment>(this);
305
32.7k
      return;
306
330k
    case FT_Org:
307
330k
      delete cast<MCOrgFragment>(this);
308
330k
      return;
309
0
    case FT_Dwarf:
310
0
      delete cast<MCDwarfLineAddrFragment>(this);
311
0
      return;
312
0
    case FT_DwarfFrame:
313
0
      delete cast<MCDwarfCallFrameFragment>(this);
314
0
      return;
315
0
    case FT_LEB:
316
0
      delete cast<MCLEBFragment>(this);
317
0
      return;
318
0
    case FT_SafeSEH:
319
0
      delete cast<MCSafeSEHFragment>(this);
320
0
      return;
321
0
    case FT_Dummy:
322
0
      delete cast<MCDummyFragment>(this);
323
0
      return;
324
648k
  }
325
648k
}
326
327
/* *** */
328
329
// Debugging methods
330
331
namespace llvm_ks {
332
333
0
raw_ostream &operator<<(raw_ostream &OS, const MCFixup &AF) {
334
0
  OS << "<MCFixup" << " Offset:" << AF.getOffset()
335
0
     << " Value:" << *AF.getValue()
336
0
     << " Kind:" << AF.getKind() << ">";
337
0
  return OS;
338
0
}
339
340
}
341
342
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
343
0
LLVM_DUMP_METHOD void MCFragment::dump() {
344
0
  raw_ostream &OS = llvm_ks::errs();
345
346
0
  OS << "<";
347
0
  switch (getKind()) {
348
0
  case MCFragment::FT_Align: OS << "MCAlignFragment"; break;
349
0
  case MCFragment::FT_Data:  OS << "MCDataFragment"; break;
350
0
  case MCFragment::FT_CompactEncodedInst:
351
0
    OS << "MCCompactEncodedInstFragment"; break;
352
0
  case MCFragment::FT_Fill:  OS << "MCFillFragment"; break;
353
0
  case MCFragment::FT_Relaxable:  OS << "MCRelaxableFragment"; break;
354
0
  case MCFragment::FT_Org:   OS << "MCOrgFragment"; break;
355
0
  case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break;
356
0
  case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break;
357
0
  case MCFragment::FT_LEB:   OS << "MCLEBFragment"; break;
358
0
  case MCFragment::FT_SafeSEH:    OS << "MCSafeSEHFragment"; break;
359
0
  case MCFragment::FT_Dummy:
360
0
    OS << "MCDummyFragment";
361
0
    break;
362
0
  }
363
364
0
  OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder
365
0
     << " Offset:" << Offset
366
0
     << " HasInstructions:" << hasInstructions() 
367
0
     << " BundlePadding:" << static_cast<unsigned>(getBundlePadding()) << ">";
368
369
0
  switch (getKind()) {
370
0
  case MCFragment::FT_Align: {
371
0
    const MCAlignFragment *AF = cast<MCAlignFragment>(this);
372
0
    if (AF->hasEmitNops())
373
0
      OS << " (emit nops)";
374
0
    OS << "\n       ";
375
0
    OS << " Alignment:" << AF->getAlignment()
376
0
       << " Value:" << AF->getValue() << " ValueSize:" << AF->getValueSize()
377
0
       << " MaxBytesToEmit:" << AF->getMaxBytesToEmit() << ">";
378
0
    break;
379
0
  }
380
0
  case MCFragment::FT_Data:  {
381
0
    const MCDataFragment *DF = cast<MCDataFragment>(this);
382
0
    OS << "\n       ";
383
0
    OS << " Contents:[";
384
0
    const SmallVectorImpl<char> &Contents = DF->getContents();
385
0
    for (unsigned i = 0, e = Contents.size(); i != e; ++i) {
386
0
      if (i) OS << ",";
387
0
      OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF);
388
0
    }
389
0
    OS << "] (" << Contents.size() << " bytes)";
390
391
0
    if (DF->fixup_begin() != DF->fixup_end()) {
392
0
      OS << ",\n       ";
393
0
      OS << " Fixups:[";
394
0
      for (MCDataFragment::const_fixup_iterator it = DF->fixup_begin(),
395
0
             ie = DF->fixup_end(); it != ie; ++it) {
396
0
        if (it != DF->fixup_begin()) OS << ",\n                ";
397
0
        OS << *it;
398
0
      }
399
0
      OS << "]";
400
0
    }
401
0
    break;
402
0
  }
403
0
  case MCFragment::FT_CompactEncodedInst: {
404
0
    const MCCompactEncodedInstFragment *CEIF =
405
0
      cast<MCCompactEncodedInstFragment>(this);
406
0
    OS << "\n       ";
407
0
    OS << " Contents:[";
408
0
    const SmallVectorImpl<char> &Contents = CEIF->getContents();
409
0
    for (unsigned i = 0, e = Contents.size(); i != e; ++i) {
410
0
      if (i) OS << ",";
411
0
      OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF);
412
0
    }
413
0
    OS << "] (" << Contents.size() << " bytes)";
414
0
    break;
415
0
  }
416
0
  case MCFragment::FT_Fill:  {
417
0
    const MCFillFragment *FF = cast<MCFillFragment>(this);
418
0
    OS << " Value:" << FF->getValue() << " Size:" << FF->getSize();
419
0
    break;
420
0
  }
421
0
  case MCFragment::FT_Relaxable:  {
422
    // const MCRelaxableFragment *F = cast<MCRelaxableFragment>(this);
423
0
    OS << "\n       ";
424
0
    OS << " Inst:";
425
0
    break;
426
0
  }
427
0
  case MCFragment::FT_Org:  {
428
0
    const MCOrgFragment *OF = cast<MCOrgFragment>(this);
429
0
    OS << "\n       ";
430
0
    OS << " Offset:" << OF->getOffset() << " Value:" << OF->getValue();
431
0
    break;
432
0
  }
433
0
  case MCFragment::FT_Dwarf:  {
434
0
    const MCDwarfLineAddrFragment *OF = cast<MCDwarfLineAddrFragment>(this);
435
0
    OS << "\n       ";
436
0
    OS << " AddrDelta:" << OF->getAddrDelta()
437
0
       << " LineDelta:" << OF->getLineDelta();
438
0
    break;
439
0
  }
440
0
  case MCFragment::FT_DwarfFrame:  {
441
0
    const MCDwarfCallFrameFragment *CF = cast<MCDwarfCallFrameFragment>(this);
442
0
    OS << "\n       ";
443
0
    OS << " AddrDelta:" << CF->getAddrDelta();
444
0
    break;
445
0
  }
446
0
  case MCFragment::FT_LEB: {
447
0
    const MCLEBFragment *LF = cast<MCLEBFragment>(this);
448
0
    OS << "\n       ";
449
0
    OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned();
450
0
    break;
451
0
  }
452
0
  case MCFragment::FT_SafeSEH: {
453
0
    const MCSafeSEHFragment *F = cast<MCSafeSEHFragment>(this);
454
0
    OS << "\n       ";
455
0
    OS << " Sym:" << F->getSymbol();
456
0
    break;
457
0
  }
458
0
  case MCFragment::FT_Dummy:
459
0
    break;
460
0
  }
461
0
  OS << ">";
462
0
}
463
464
0
LLVM_DUMP_METHOD void MCAssembler::dump() {
465
0
  raw_ostream &OS = llvm_ks::errs();
466
467
0
  OS << "<MCAssembler\n";
468
0
  OS << "  Sections:[\n    ";
469
0
  for (iterator it = begin(), ie = end(); it != ie; ++it) {
470
0
    if (it != begin()) OS << ",\n    ";
471
0
    it->dump();
472
0
  }
473
0
  OS << "],\n";
474
0
  OS << "  Symbols:[";
475
476
0
  for (symbol_iterator it = symbol_begin(), ie = symbol_end(); it != ie; ++it) {
477
0
    if (it != symbol_begin()) OS << ",\n           ";
478
0
    OS << "(";
479
0
    it->dump();
480
0
    OS << ", Index:" << it->getIndex() << ", ";
481
0
    OS << ")";
482
0
  }
483
0
  OS << "]>\n";
484
0
}
485
#endif