@@ -206,7 +206,7 @@ raw_ostream &print_state(raw_ostream &OS, const State &S,
206
206
} else
207
207
OS << " None" ;
208
208
OS << " ," ;
209
- OS << " LastStackGrowingInsts(" << S.LastStackGrowingInsts .size () << " )>" ;
209
+ OS << " LastStackGrowingInsts(" << S.LastStackGrowingInsts .size () << " )> " ;
210
210
return OS;
211
211
}
212
212
@@ -224,6 +224,86 @@ class StackClashStatePrinter {
224
224
explicit StackClashStatePrinter (const BinaryContext &BC) : BC(BC) {}
225
225
};
226
226
227
+ bool checkNonConstSPOffsetChange (const BinaryContext &BC, BinaryFunction &BF,
228
+ const MCInst &Point, const State &Cur,
229
+ State *Next = nullptr ) {
230
+ const MCPhysReg SP = BC.MIB ->getStackPointer ();
231
+ bool IsNonConstantSPOffsetChange = false ;
232
+ if (BC.MIB ->hasDefOfPhysReg (Point, SP)) {
233
+ IsNonConstantSPOffsetChange = true ;
234
+
235
+ // Next, validate that we can track by how much the SP
236
+ // value changes. This should be a constant amount.
237
+ // Else, if we cannot determine the fixed offset, mark this location as
238
+ // needing a report that this potentially changes the SP value by a
239
+ // non-constant amount, and hence violates stack-clash properties.
240
+ if (Next)
241
+ Next->LastStackGrowingInsts .insert (MCInstInBBReference::get (&Point, BF));
242
+ if (auto OC = BC.MIB ->getOffsetChange (Point, Cur.RegConstValues ,
243
+ Cur.RegMaxValues );
244
+ OC && OC.ToReg == SP) {
245
+ if (OC.FromReg == SP) {
246
+ IsNonConstantSPOffsetChange = false ;
247
+ assert (OC.MaxOffsetChange );
248
+ if (Next) {
249
+ if (*OC.MaxOffsetChange < 0 )
250
+ Next->MaxOffsetSinceLastProbe =
251
+ *Next->MaxOffsetSinceLastProbe - *OC.MaxOffsetChange ;
252
+ if (OC.OffsetChange && Next->SPFixedOffsetFromOrig )
253
+ Next->SPFixedOffsetFromOrig =
254
+ *Next->SPFixedOffsetFromOrig + *OC.OffsetChange ;
255
+ // FIXME: add test case for this if test.
256
+ #if 0
257
+ if (IsPreIndexOffsetChange)
258
+ Next.MaxOffsetSinceLastProbe =
259
+ *Next.MaxOffsetSinceLastProbe - StackAccessOffset;
260
+ #endif
261
+ LLVM_DEBUG ({
262
+ dbgs () << " Found SP Offset change: " ;
263
+ BC.printInstruction (dbgs (), Point);
264
+ dbgs () << " OffsetChange: " << OC.OffsetChange
265
+ << " ; MaxOffsetChange: " << OC.MaxOffsetChange
266
+ << " ; new MaxOffsetSinceLastProbe: "
267
+ << Next->MaxOffsetSinceLastProbe
268
+ << " ; new SPFixedOffsetFromOrig: "
269
+ << Next->SPFixedOffsetFromOrig
270
+ << " \n " ;
271
+ });
272
+ }
273
+ // assert(!OC.IsPreIndexOffsetChange || IsStackAccess);
274
+ if (Next)
275
+ assert (*Next->MaxOffsetSinceLastProbe >= 0 );
276
+ } else if (Cur.Reg2MaxOffset && Cur.Reg2MaxOffset ->contains (OC.FromReg ) &&
277
+ OC.OffsetChange ) {
278
+ IsNonConstantSPOffsetChange = false ;
279
+ const int64_t MaxOffset = Cur.Reg2MaxOffset ->find (OC.FromReg )->second ;
280
+ if (Next) {
281
+ Next->MaxOffsetSinceLastProbe = MaxOffset - *OC.OffsetChange ;
282
+ Next->SPFixedOffsetFromOrig = std::nullopt;
283
+ }
284
+ }
285
+ }
286
+ }
287
+ uint64_t Mask = 0 ;
288
+ if (MCPhysReg FromReg, ToReg;
289
+ BC.MIB ->isMaskLowerBitsInReg (Point, FromReg, ToReg, Mask) &&
290
+ Cur.Reg2MaxOffset && Cur.Reg2MaxOffset ->contains (FromReg)) {
291
+ // handle SP-aligning patterns like
292
+ // sub x9, sp, #0x1d0
293
+ // and sp, x9, #0xffffffffffffff80
294
+ uint64_t BitsToZeroMask = ~Mask;
295
+ int64_t MaxOffsetChange = BitsToZeroMask + 1 ;
296
+ if (Next) {
297
+ Next->MaxOffsetSinceLastProbe =
298
+ Cur.Reg2MaxOffset ->find (FromReg)->second + MaxOffsetChange;
299
+ Next->SPFixedOffsetFromOrig = std::nullopt;
300
+ }
301
+ IsNonConstantSPOffsetChange = false ;
302
+ }
303
+
304
+ return IsNonConstantSPOffsetChange;
305
+ }
306
+
227
307
class StackClashDFAnalysis
228
308
: public DataflowAnalysis<StackClashDFAnalysis, State, false /* Forward*/ ,
229
309
StackClashStatePrinter> {
@@ -356,13 +436,15 @@ class StackClashDFAnalysis
356
436
MCPhysReg FixedOffsetRegJustSet = BC.MIB ->getNoRegister ();
357
437
if (auto OC = BC.MIB ->getOffsetChange (Point, Cur.RegConstValues ,
358
438
Cur.RegMaxValues ))
359
- if (Next.Reg2MaxOffset ) {
439
+ if (Next.Reg2MaxOffset && OC.OffsetChange ) {
440
+ int64_t Offset = *OC.OffsetChange ;
360
441
if (OC.FromReg == SP) {
361
- (*Next.Reg2MaxOffset )[OC.ToReg ] = *Cur.MaxOffsetSinceLastProbe ;
442
+ (*Next.Reg2MaxOffset )[OC.ToReg ] =
443
+ *Cur.MaxOffsetSinceLastProbe - Offset;
362
444
FixedOffsetRegJustSet = OC.ToReg ;
363
445
} else if (auto I = Cur.Reg2MaxOffset ->find (OC.FromReg );
364
446
I != Cur.Reg2MaxOffset ->end ()) {
365
- (*Next.Reg2MaxOffset )[OC.ToReg ] = (*I).second ;
447
+ (*Next.Reg2MaxOffset )[OC.ToReg ] = (*I).second - Offset ;
366
448
FixedOffsetRegJustSet = OC.ToReg ;
367
449
}
368
450
}
@@ -380,60 +462,18 @@ class StackClashDFAnalysis
380
462
}
381
463
}
382
464
383
- if (BC.MIB ->hasDefOfPhysReg (Point, SP)) {
384
- // Next, validate that we can track by how much the SP
385
- // value changes. This should be a constant amount.
386
- // Else, if we cannot determine the fixed offset, mark this location as
387
- // needing a report that this potentially changes the SP value by a
388
- // non-constant amount, and hence violates stack-clash properties.
389
- Next.LastStackGrowingInsts .insert (MCInstInBBReference::get (&Point, BF));
390
- if (auto OC = BC.MIB ->getOffsetChange (Point, Cur.RegConstValues ,
391
- Cur.RegMaxValues );
392
- OC && OC.ToReg == SP) {
393
- if (OC.FromReg == SP) {
394
- assert (OC.MaxOffsetChange );
395
- if (*OC.MaxOffsetChange < 0 )
396
- Next.MaxOffsetSinceLastProbe =
397
- *Next.MaxOffsetSinceLastProbe - *OC.MaxOffsetChange ;
398
- if (OC.OffsetChange && Next.SPFixedOffsetFromOrig )
399
- Next.SPFixedOffsetFromOrig =
400
- *Next.SPFixedOffsetFromOrig + *OC.OffsetChange ;
401
- // FIXME: add test case for this if test.
402
- #if 0
403
- if (IsPreIndexOffsetChange)
404
- Next.MaxOffsetSinceLastProbe =
405
- *Next.MaxOffsetSinceLastProbe - StackAccessOffset;
406
- #endif
407
- LLVM_DEBUG ({
408
- dbgs () << " Found SP Offset change: " ;
409
- BC.printInstruction (dbgs (), Point);
410
- dbgs () << " OffsetChange: " << OC.OffsetChange
411
- << " ; MaxOffsetChange: " << OC.MaxOffsetChange
412
- << " ; new MaxOffsetSinceLastProbe: "
413
- << Next.MaxOffsetSinceLastProbe
414
- << " ; new SPFixedOffsetFromOrig: "
415
- << Next.SPFixedOffsetFromOrig
416
- << " ; IsStackAccess:" << IsStackAccess
417
- << " ; StackAccessOffset: " << StackAccessOffset << " \n " ;
418
- });
419
- assert (!OC.IsPreIndexOffsetChange || IsStackAccess);
420
- assert (*Next.MaxOffsetSinceLastProbe >= 0 );
421
- } else if (
422
- Cur.Reg2MaxOffset && Cur.Reg2MaxOffset ->contains (OC.FromReg ) &&
423
- OC.OffsetChange ==
424
- 0 /* FIXME: also handle other offset changes if needed. */ ) {
425
- const int64_t MaxOffset = Cur.Reg2MaxOffset ->find (OC.FromReg )->second ;
426
- Next.MaxOffsetSinceLastProbe = MaxOffset;
427
- }
428
- } else {
429
- Next.MaxOffsetSinceLastProbe .reset ();
430
- Next.SPFixedOffsetFromOrig
431
- .reset (); // FIXME - should I make this the empty set?
432
- LLVM_DEBUG ({
433
- dbgs () << " Found non-const SP Offset change: " ;
434
- BC.printInstruction (dbgs (), Point);
435
- });
436
- }
465
+ bool IsNonConstantSPOffsetChange =
466
+ checkNonConstSPOffsetChange (BC, BF, Point, Cur, &Next);
467
+ if (IsNonConstantSPOffsetChange) {
468
+ Next.MaxOffsetSinceLastProbe .reset ();
469
+ Next.SPFixedOffsetFromOrig
470
+ .reset (); // FIXME - should I make this the empty set?
471
+ // FIXME - should I make the Reg trackers empty sets
472
+ // here?
473
+ LLVM_DEBUG ({
474
+ dbgs () << " Found non-const SP Offset change: " ;
475
+ BC.printInstruction (dbgs (), Point);
476
+ });
437
477
}
438
478
439
479
return Next;
@@ -461,7 +501,6 @@ void StackClashAnalysis::runOnFunction(
461
501
StackClashDFAnalysis SCDFA (BF, AllocatorId);
462
502
SCDFA.run ();
463
503
BinaryContext &BC = BF.getBinaryContext ();
464
- const MCPhysReg SP = BC.MIB ->getStackPointer ();
465
504
466
505
// Now iterate over the basic blocks to indicate where something needs
467
506
// to be reported.
@@ -498,31 +537,16 @@ void StackClashAnalysis::runOnFunction(
498
537
// Else, if we cannot determine the fixed offset, mark this location
499
538
// as needing a report that this potentially changes the SP value by a
500
539
// non-constant amount, and hence violates stack-clash properties.
501
- if (auto OC =
502
- BC.MIB ->getOffsetChange (Inst, S.RegConstValues , S.RegMaxValues );
503
- BC.MIB ->hasDefOfPhysReg (Inst, SP) &&
504
- !(OC && OC.ToReg == SP && OC.FromReg == SP)) {
505
- // If this is a register move from a register that we know contains
506
- // a value that is a fixed offset from the SP at the start of the
507
- // function into the SP, then we know this is probably fine.
508
- // Typical case is moving the frame pointer to the stack pointer
509
- // in the function epilogue.
510
- bool IsFixedRegToSPMove = OC && OC.ToReg == SP && S.Reg2MaxOffset &&
511
- S.Reg2MaxOffset ->contains (OC.FromReg );
512
- if (IsFixedRegToSPMove) {
513
- S.MaxOffsetSinceLastProbe =
514
- S.Reg2MaxOffset ->find (OC.FromReg )->second ;
515
- } else {
516
- // mark to report that this may be an SP change that is not a
517
- // constant amount.
518
- LLVM_DEBUG ({
519
- dbgs () << " Found SP Offset change that may not be a constant "
520
- " amount: " ;
521
- BC.printInstruction (dbgs (), Inst);
522
- });
523
- SCIAnnotations.push_back (
524
- StackClashIssue::createNonConstantSPChangeData ());
525
- }
540
+ if (checkNonConstSPOffsetChange (BC, BF, Inst, S)) {
541
+ // mark to report that this may be an SP change that is not a
542
+ // constant amount.
543
+ LLVM_DEBUG ({
544
+ dbgs () << " Found SP Offset change that may not be a constant "
545
+ " amount: " ;
546
+ BC.printInstruction (dbgs (), Inst);
547
+ });
548
+ SCIAnnotations.push_back (
549
+ StackClashIssue::createNonConstantSPChangeData ());
526
550
}
527
551
// merge and add annotations
528
552
if (SCIAnnotations.size () == 0 )
0 commit comments