github.com/cnboonhan/delve@v0.0.0-20230908061759-363f2388c2fb/pkg/dwarf/frame/table.go (about) 1 package frame 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 8 "github.com/go-delve/delve/pkg/dwarf/leb128" 9 ) 10 11 // DWRule wrapper of rule defined for register values. 12 type DWRule struct { 13 Rule Rule 14 Offset int64 15 Reg uint64 16 Expression []byte 17 } 18 19 // FrameContext wrapper of FDE context 20 type FrameContext struct { 21 loc uint64 22 order binary.ByteOrder 23 address uint64 24 CFA DWRule 25 Regs map[uint64]DWRule 26 initialRegs map[uint64]DWRule 27 buf *bytes.Buffer 28 cie *CommonInformationEntry 29 RetAddrReg uint64 30 codeAlignment uint64 31 dataAlignment int64 32 rememberedState *stateStack 33 } 34 35 type rowState struct { 36 cfa DWRule 37 regs map[uint64]DWRule 38 } 39 40 // stateStack is a stack where `DW_CFA_remember_state` pushes 41 // its CFA and registers state and `DW_CFA_restore_state` 42 // pops them. 43 type stateStack struct { 44 items []rowState 45 } 46 47 func newStateStack() *stateStack { 48 return &stateStack{ 49 items: make([]rowState, 0), 50 } 51 } 52 53 func (stack *stateStack) push(state rowState) { 54 stack.items = append(stack.items, state) 55 } 56 57 func (stack *stateStack) pop() rowState { 58 restored := stack.items[len(stack.items)-1] 59 stack.items = stack.items[0 : len(stack.items)-1] 60 return restored 61 } 62 63 // Instructions used to recreate the table from the .debug_frame data. 64 const ( 65 DW_CFA_nop = 0x0 // No ops 66 DW_CFA_set_loc = 0x01 // op1: address 67 DW_CFA_advance_loc1 = iota // op1: 1-bytes delta 68 DW_CFA_advance_loc2 // op1: 2-byte delta 69 DW_CFA_advance_loc4 // op1: 4-byte delta 70 DW_CFA_offset_extended // op1: ULEB128 register, op2: ULEB128 offset 71 DW_CFA_restore_extended // op1: ULEB128 register 72 DW_CFA_undefined // op1: ULEB128 register 73 DW_CFA_same_value // op1: ULEB128 register 74 DW_CFA_register // op1: ULEB128 register, op2: ULEB128 register 75 DW_CFA_remember_state // No ops 76 DW_CFA_restore_state // No ops 77 DW_CFA_def_cfa // op1: ULEB128 register, op2: ULEB128 offset 78 DW_CFA_def_cfa_register // op1: ULEB128 register 79 DW_CFA_def_cfa_offset // op1: ULEB128 offset 80 DW_CFA_def_cfa_expression // op1: BLOCK 81 DW_CFA_expression // op1: ULEB128 register, op2: BLOCK 82 DW_CFA_offset_extended_sf // op1: ULEB128 register, op2: SLEB128 BLOCK 83 DW_CFA_def_cfa_sf // op1: ULEB128 register, op2: SLEB128 offset 84 DW_CFA_def_cfa_offset_sf // op1: SLEB128 offset 85 DW_CFA_val_offset // op1: ULEB128, op2: ULEB128 86 DW_CFA_val_offset_sf // op1: ULEB128, op2: SLEB128 87 DW_CFA_val_expression // op1: ULEB128, op2: BLOCK 88 DW_CFA_lo_user = 0x1c // op1: BLOCK 89 DW_CFA_hi_user = 0x3f // op1: ULEB128 register, op2: BLOCK 90 DW_CFA_advance_loc = (0x1 << 6) // High 2 bits: 0x1, low 6: delta 91 DW_CFA_offset = (0x2 << 6) // High 2 bits: 0x2, low 6: register 92 DW_CFA_restore = (0x3 << 6) // High 2 bits: 0x3, low 6: register 93 ) 94 95 // Rule rule defined for register values. 96 type Rule byte 97 98 const ( 99 RuleUndefined Rule = iota 100 RuleSameVal 101 RuleOffset 102 RuleValOffset 103 RuleRegister 104 RuleExpression 105 RuleValExpression 106 RuleArchitectural 107 RuleCFA // Value is rule.Reg + rule.Offset 108 RuleFramePointer // Value is stored at address rule.Reg + rule.Offset, but only if it's less than the current CFA, otherwise same value 109 ) 110 111 const low_6_offset = 0x3f 112 113 type instruction func(frame *FrameContext) 114 115 // // Mapping from DWARF opcode to function. 116 var fnlookup = map[byte]instruction{ 117 DW_CFA_advance_loc: advanceloc, 118 DW_CFA_offset: offset, 119 DW_CFA_restore: restore, 120 DW_CFA_set_loc: setloc, 121 DW_CFA_advance_loc1: advanceloc1, 122 DW_CFA_advance_loc2: advanceloc2, 123 DW_CFA_advance_loc4: advanceloc4, 124 DW_CFA_offset_extended: offsetextended, 125 DW_CFA_restore_extended: restoreextended, 126 DW_CFA_undefined: undefined, 127 DW_CFA_same_value: samevalue, 128 DW_CFA_register: register, 129 DW_CFA_remember_state: rememberstate, 130 DW_CFA_restore_state: restorestate, 131 DW_CFA_def_cfa: defcfa, 132 DW_CFA_def_cfa_register: defcfaregister, 133 DW_CFA_def_cfa_offset: defcfaoffset, 134 DW_CFA_def_cfa_expression: defcfaexpression, 135 DW_CFA_expression: expression, 136 DW_CFA_offset_extended_sf: offsetextendedsf, 137 DW_CFA_def_cfa_sf: defcfasf, 138 DW_CFA_def_cfa_offset_sf: defcfaoffsetsf, 139 DW_CFA_val_offset: valoffset, 140 DW_CFA_val_offset_sf: valoffsetsf, 141 DW_CFA_val_expression: valexpression, 142 DW_CFA_lo_user: louser, 143 DW_CFA_hi_user: hiuser, 144 } 145 146 func executeCIEInstructions(cie *CommonInformationEntry) *FrameContext { 147 initialInstructions := make([]byte, len(cie.InitialInstructions)) 148 copy(initialInstructions, cie.InitialInstructions) 149 frame := &FrameContext{ 150 cie: cie, 151 Regs: make(map[uint64]DWRule), 152 RetAddrReg: cie.ReturnAddressRegister, 153 initialRegs: make(map[uint64]DWRule), 154 codeAlignment: cie.CodeAlignmentFactor, 155 dataAlignment: cie.DataAlignmentFactor, 156 buf: bytes.NewBuffer(initialInstructions), 157 rememberedState: newStateStack(), 158 } 159 160 frame.executeDwarfProgram() 161 return frame 162 } 163 164 // Unwind the stack to find the return address register. 165 func executeDwarfProgramUntilPC(fde *FrameDescriptionEntry, pc uint64) *FrameContext { 166 frame := executeCIEInstructions(fde.CIE) 167 frame.order = fde.order 168 frame.loc = fde.Begin() 169 frame.address = pc 170 frame.ExecuteUntilPC(fde.Instructions) 171 172 return frame 173 } 174 175 func (frame *FrameContext) executeDwarfProgram() { 176 for frame.buf.Len() > 0 { 177 executeDwarfInstruction(frame) 178 } 179 } 180 181 // ExecuteUntilPC execute dwarf instructions. 182 func (frame *FrameContext) ExecuteUntilPC(instructions []byte) { 183 frame.buf.Truncate(0) 184 frame.buf.Write(instructions) 185 186 // We only need to execute the instructions until 187 // ctx.loc > ctx.address (which is the address we 188 // are currently at in the traced process). 189 for frame.address >= frame.loc && frame.buf.Len() > 0 { 190 executeDwarfInstruction(frame) 191 } 192 } 193 194 func executeDwarfInstruction(frame *FrameContext) { 195 instruction, err := frame.buf.ReadByte() 196 if err != nil { 197 panic("Could not read from instruction buffer") 198 } 199 200 if instruction == DW_CFA_nop { 201 return 202 } 203 204 fn := lookupFunc(instruction, frame.buf) 205 206 fn(frame) 207 } 208 209 func lookupFunc(instruction byte, buf *bytes.Buffer) instruction { 210 const high_2_bits = 0xc0 211 var restore bool 212 213 // Special case the 3 opcodes that have their argument encoded in the opcode itself. 214 switch instruction & high_2_bits { 215 case DW_CFA_advance_loc: 216 instruction = DW_CFA_advance_loc 217 restore = true 218 219 case DW_CFA_offset: 220 instruction = DW_CFA_offset 221 restore = true 222 223 case DW_CFA_restore: 224 instruction = DW_CFA_restore 225 restore = true 226 } 227 228 if restore { 229 // Restore the last byte as it actually contains the argument for the opcode. 230 err := buf.UnreadByte() 231 if err != nil { 232 panic("Could not unread byte") 233 } 234 } 235 236 fn, ok := fnlookup[instruction] 237 if !ok { 238 panic(fmt.Sprintf("Encountered an unexpected DWARF CFA opcode: %#v", instruction)) 239 } 240 241 return fn 242 } 243 244 func advanceloc(frame *FrameContext) { 245 b, err := frame.buf.ReadByte() 246 if err != nil { 247 panic("Could not read byte") 248 } 249 250 delta := b & low_6_offset 251 frame.loc += uint64(delta) * frame.codeAlignment 252 } 253 254 func advanceloc1(frame *FrameContext) { 255 delta, err := frame.buf.ReadByte() 256 if err != nil { 257 panic("Could not read byte") 258 } 259 260 frame.loc += uint64(delta) * frame.codeAlignment 261 } 262 263 func advanceloc2(frame *FrameContext) { 264 var delta uint16 265 binary.Read(frame.buf, frame.order, &delta) 266 267 frame.loc += uint64(delta) * frame.codeAlignment 268 } 269 270 func advanceloc4(frame *FrameContext) { 271 var delta uint32 272 binary.Read(frame.buf, frame.order, &delta) 273 274 frame.loc += uint64(delta) * frame.codeAlignment 275 } 276 277 func offset(frame *FrameContext) { 278 b, err := frame.buf.ReadByte() 279 if err != nil { 280 panic(err) 281 } 282 283 var ( 284 reg = b & low_6_offset 285 offset, _ = leb128.DecodeUnsigned(frame.buf) 286 ) 287 288 frame.Regs[uint64(reg)] = DWRule{Offset: int64(offset) * frame.dataAlignment, Rule: RuleOffset} 289 } 290 291 func restore(frame *FrameContext) { 292 b, err := frame.buf.ReadByte() 293 if err != nil { 294 panic(err) 295 } 296 297 reg := uint64(b & low_6_offset) 298 oldrule, ok := frame.initialRegs[reg] 299 if ok { 300 frame.Regs[reg] = DWRule{Offset: oldrule.Offset, Rule: RuleOffset} 301 } else { 302 frame.Regs[reg] = DWRule{Rule: RuleUndefined} 303 } 304 } 305 306 func setloc(frame *FrameContext) { 307 var loc uint64 308 binary.Read(frame.buf, frame.order, &loc) 309 310 frame.loc = loc + frame.cie.staticBase 311 } 312 313 func offsetextended(frame *FrameContext) { 314 var ( 315 reg, _ = leb128.DecodeUnsigned(frame.buf) 316 offset, _ = leb128.DecodeUnsigned(frame.buf) 317 ) 318 319 frame.Regs[reg] = DWRule{Offset: int64(offset) * frame.dataAlignment, Rule: RuleOffset} 320 } 321 322 func undefined(frame *FrameContext) { 323 reg, _ := leb128.DecodeUnsigned(frame.buf) 324 frame.Regs[reg] = DWRule{Rule: RuleUndefined} 325 } 326 327 func samevalue(frame *FrameContext) { 328 reg, _ := leb128.DecodeUnsigned(frame.buf) 329 frame.Regs[reg] = DWRule{Rule: RuleSameVal} 330 } 331 332 func register(frame *FrameContext) { 333 reg1, _ := leb128.DecodeUnsigned(frame.buf) 334 reg2, _ := leb128.DecodeUnsigned(frame.buf) 335 frame.Regs[reg1] = DWRule{Reg: reg2, Rule: RuleRegister} 336 } 337 338 func rememberstate(frame *FrameContext) { 339 clonedRegs := make(map[uint64]DWRule, len(frame.Regs)) 340 for k, v := range frame.Regs { 341 clonedRegs[k] = v 342 } 343 frame.rememberedState.push(rowState{cfa: frame.CFA, regs: clonedRegs}) 344 } 345 346 func restorestate(frame *FrameContext) { 347 restored := frame.rememberedState.pop() 348 349 frame.CFA = restored.cfa 350 frame.Regs = restored.regs 351 } 352 353 func restoreextended(frame *FrameContext) { 354 reg, _ := leb128.DecodeUnsigned(frame.buf) 355 356 oldrule, ok := frame.initialRegs[reg] 357 if ok { 358 frame.Regs[reg] = DWRule{Offset: oldrule.Offset, Rule: RuleOffset} 359 } else { 360 frame.Regs[reg] = DWRule{Rule: RuleUndefined} 361 } 362 } 363 364 func defcfa(frame *FrameContext) { 365 reg, _ := leb128.DecodeUnsigned(frame.buf) 366 offset, _ := leb128.DecodeUnsigned(frame.buf) 367 368 frame.CFA.Rule = RuleCFA 369 frame.CFA.Reg = reg 370 frame.CFA.Offset = int64(offset) 371 } 372 373 func defcfaregister(frame *FrameContext) { 374 reg, _ := leb128.DecodeUnsigned(frame.buf) 375 frame.CFA.Reg = reg 376 } 377 378 func defcfaoffset(frame *FrameContext) { 379 offset, _ := leb128.DecodeUnsigned(frame.buf) 380 frame.CFA.Offset = int64(offset) 381 } 382 383 func defcfasf(frame *FrameContext) { 384 reg, _ := leb128.DecodeUnsigned(frame.buf) 385 offset, _ := leb128.DecodeSigned(frame.buf) 386 387 frame.CFA.Rule = RuleCFA 388 frame.CFA.Reg = reg 389 frame.CFA.Offset = offset * frame.dataAlignment 390 } 391 392 func defcfaoffsetsf(frame *FrameContext) { 393 offset, _ := leb128.DecodeSigned(frame.buf) 394 offset *= frame.dataAlignment 395 frame.CFA.Offset = offset 396 } 397 398 func defcfaexpression(frame *FrameContext) { 399 var ( 400 l, _ = leb128.DecodeUnsigned(frame.buf) 401 expr = frame.buf.Next(int(l)) 402 ) 403 404 frame.CFA.Expression = expr 405 frame.CFA.Rule = RuleExpression 406 } 407 408 func expression(frame *FrameContext) { 409 var ( 410 reg, _ = leb128.DecodeUnsigned(frame.buf) 411 l, _ = leb128.DecodeUnsigned(frame.buf) 412 expr = frame.buf.Next(int(l)) 413 ) 414 415 frame.Regs[reg] = DWRule{Rule: RuleExpression, Expression: expr} 416 } 417 418 func offsetextendedsf(frame *FrameContext) { 419 var ( 420 reg, _ = leb128.DecodeUnsigned(frame.buf) 421 offset, _ = leb128.DecodeSigned(frame.buf) 422 ) 423 424 frame.Regs[reg] = DWRule{Offset: offset * frame.dataAlignment, Rule: RuleOffset} 425 } 426 427 func valoffset(frame *FrameContext) { 428 var ( 429 reg, _ = leb128.DecodeUnsigned(frame.buf) 430 offset, _ = leb128.DecodeUnsigned(frame.buf) 431 ) 432 433 frame.Regs[reg] = DWRule{Offset: int64(offset), Rule: RuleValOffset} 434 } 435 436 func valoffsetsf(frame *FrameContext) { 437 var ( 438 reg, _ = leb128.DecodeUnsigned(frame.buf) 439 offset, _ = leb128.DecodeSigned(frame.buf) 440 ) 441 442 frame.Regs[reg] = DWRule{Offset: offset * frame.dataAlignment, Rule: RuleValOffset} 443 } 444 445 func valexpression(frame *FrameContext) { 446 var ( 447 reg, _ = leb128.DecodeUnsigned(frame.buf) 448 l, _ = leb128.DecodeUnsigned(frame.buf) 449 expr = frame.buf.Next(int(l)) 450 ) 451 452 frame.Regs[reg] = DWRule{Rule: RuleValExpression, Expression: expr} 453 } 454 455 func louser(frame *FrameContext) { 456 frame.buf.Next(1) 457 } 458 459 func hiuser(frame *FrameContext) { 460 frame.buf.Next(1) 461 }