github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/dwarf/frame/table.go (about) 1 // The MIT License (MIT) 2 3 // Copyright (c) 2014 Derek Parker 4 5 // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 // this software and associated documentation files (the "Software"), to deal in 7 // the Software without restriction, including without limitation the rights to 8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 // the Software, and to permit persons to whom the Software is furnished to do so, 10 // subject to the following conditions: 11 12 // The above copyright notice and this permission notice shall be included in all 13 // copies or substantial portions of the Software. 14 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22 package frame 23 24 import ( 25 "bytes" 26 "encoding/binary" 27 "fmt" 28 29 "github.com/Rookout/GoSDK/pkg/services/instrumentation/dwarf/util" 30 ) 31 32 33 type DWRule struct { 34 Rule Rule 35 Offset int64 36 Reg uint64 37 Expression []byte 38 } 39 40 41 type FrameContext struct { 42 loc uint64 43 order binary.ByteOrder 44 address uint64 45 CFA DWRule 46 Regs map[uint64]DWRule 47 initialRegs map[uint64]DWRule 48 prevRegs map[uint64]DWRule 49 buf *bytes.Buffer 50 cie *CommonInformationEntry 51 RetAddrReg uint64 52 codeAlignment uint64 53 dataAlignment int64 54 } 55 56 57 const ( 58 DW_CFA_nop = 0x0 59 DW_CFA_set_loc = 0x01 60 DW_CFA_advance_loc1 = iota 61 DW_CFA_advance_loc2 62 DW_CFA_advance_loc4 63 DW_CFA_offset_extended 64 DW_CFA_restore_extended 65 DW_CFA_undefined 66 DW_CFA_same_value 67 DW_CFA_register 68 DW_CFA_remember_state 69 DW_CFA_restore_state 70 DW_CFA_def_cfa 71 DW_CFA_def_cfa_register 72 DW_CFA_def_cfa_offset 73 DW_CFA_def_cfa_expression 74 DW_CFA_expression 75 DW_CFA_offset_extended_sf 76 DW_CFA_def_cfa_sf 77 DW_CFA_def_cfa_offset_sf 78 DW_CFA_val_offset 79 DW_CFA_val_offset_sf 80 DW_CFA_val_expression 81 DW_CFA_lo_user = 0x1c 82 DW_CFA_hi_user = 0x3f 83 DW_CFA_advance_loc = 0x1 << 6 84 DW_CFA_offset = 0x2 << 6 85 DW_CFA_restore = 0x3 << 6 86 ) 87 88 89 type Rule byte 90 91 const ( 92 RuleUndefined Rule = iota 93 RuleSameVal 94 RuleOffset 95 RuleValOffset 96 RuleRegister 97 RuleExpression 98 RuleValExpression 99 RuleArchitectural 100 RuleCFA 101 RuleFramePointer 102 ) 103 104 const low_6_offset = 0x3f 105 106 type instruction func(frame *FrameContext) 107 108 109 var fnlookup = map[byte]instruction{ 110 DW_CFA_advance_loc: advanceloc, 111 DW_CFA_offset: offset, 112 DW_CFA_restore: restore, 113 DW_CFA_set_loc: setloc, 114 DW_CFA_advance_loc1: advanceloc1, 115 DW_CFA_advance_loc2: advanceloc2, 116 DW_CFA_advance_loc4: advanceloc4, 117 DW_CFA_offset_extended: offsetextended, 118 DW_CFA_restore_extended: restoreextended, 119 DW_CFA_undefined: undefined, 120 DW_CFA_same_value: samevalue, 121 DW_CFA_register: register, 122 DW_CFA_remember_state: rememberstate, 123 DW_CFA_restore_state: restorestate, 124 DW_CFA_def_cfa: defcfa, 125 DW_CFA_def_cfa_register: defcfaregister, 126 DW_CFA_def_cfa_offset: defcfaoffset, 127 DW_CFA_def_cfa_expression: defcfaexpression, 128 DW_CFA_expression: expression, 129 DW_CFA_offset_extended_sf: offsetextendedsf, 130 DW_CFA_def_cfa_sf: defcfasf, 131 DW_CFA_def_cfa_offset_sf: defcfaoffsetsf, 132 DW_CFA_val_offset: valoffset, 133 DW_CFA_val_offset_sf: valoffsetsf, 134 DW_CFA_val_expression: valexpression, 135 DW_CFA_lo_user: louser, 136 DW_CFA_hi_user: hiuser, 137 } 138 139 func executeCIEInstructions(cie *CommonInformationEntry) *FrameContext { 140 initialInstructions := make([]byte, len(cie.InitialInstructions)) 141 copy(initialInstructions, cie.InitialInstructions) 142 frame := &FrameContext{ 143 cie: cie, 144 Regs: make(map[uint64]DWRule), 145 RetAddrReg: cie.ReturnAddressRegister, 146 initialRegs: make(map[uint64]DWRule), 147 prevRegs: make(map[uint64]DWRule), 148 codeAlignment: cie.CodeAlignmentFactor, 149 dataAlignment: cie.DataAlignmentFactor, 150 buf: bytes.NewBuffer(initialInstructions), 151 } 152 153 frame.executeDwarfProgram() 154 return frame 155 } 156 157 158 func executeDwarfProgramUntilPC(fde *FrameDescriptionEntry, pc uint64) *FrameContext { 159 frame := executeCIEInstructions(fde.CIE) 160 frame.order = fde.order 161 frame.loc = fde.Begin() 162 frame.address = pc 163 frame.ExecuteUntilPC(fde.Instructions) 164 165 return frame 166 } 167 168 func (frame *FrameContext) executeDwarfProgram() { 169 for frame.buf.Len() > 0 { 170 executeDwarfInstruction(frame) 171 } 172 } 173 174 175 func (frame *FrameContext) ExecuteUntilPC(instructions []byte) { 176 frame.buf.Truncate(0) 177 frame.buf.Write(instructions) 178 179 180 181 182 for frame.address >= frame.loc && frame.buf.Len() > 0 { 183 executeDwarfInstruction(frame) 184 } 185 } 186 187 func executeDwarfInstruction(frame *FrameContext) { 188 instruction, err := frame.buf.ReadByte() 189 if err != nil { 190 panic("Could not read from instruction buffer") 191 } 192 193 if instruction == DW_CFA_nop { 194 return 195 } 196 197 fn := lookupFunc(instruction, frame.buf) 198 199 fn(frame) 200 } 201 202 func lookupFunc(instruction byte, buf *bytes.Buffer) instruction { 203 const high_2_bits = 0xc0 204 var restore bool 205 206 207 switch instruction & high_2_bits { 208 case DW_CFA_advance_loc: 209 instruction = DW_CFA_advance_loc 210 restore = true 211 212 case DW_CFA_offset: 213 instruction = DW_CFA_offset 214 restore = true 215 216 case DW_CFA_restore: 217 instruction = DW_CFA_restore 218 restore = true 219 } 220 221 if restore { 222 223 err := buf.UnreadByte() 224 if err != nil { 225 panic("Could not unread byte") 226 } 227 } 228 229 fn, ok := fnlookup[instruction] 230 if !ok { 231 panic(fmt.Sprintf("Encountered an unexpected DWARF CFA opcode: %#v", instruction)) 232 } 233 234 return fn 235 } 236 237 func advanceloc(frame *FrameContext) { 238 b, err := frame.buf.ReadByte() 239 if err != nil { 240 panic("Could not read byte") 241 } 242 243 delta := b & low_6_offset 244 frame.loc += uint64(delta) * frame.codeAlignment 245 } 246 247 func advanceloc1(frame *FrameContext) { 248 delta, err := frame.buf.ReadByte() 249 if err != nil { 250 panic("Could not read byte") 251 } 252 253 frame.loc += uint64(delta) * frame.codeAlignment 254 } 255 256 func advanceloc2(frame *FrameContext) { 257 var delta uint16 258 binary.Read(frame.buf, frame.order, &delta) 259 260 frame.loc += uint64(delta) * frame.codeAlignment 261 } 262 263 func advanceloc4(frame *FrameContext) { 264 var delta uint32 265 binary.Read(frame.buf, frame.order, &delta) 266 267 frame.loc += uint64(delta) * frame.codeAlignment 268 } 269 270 func offset(frame *FrameContext) { 271 b, err := frame.buf.ReadByte() 272 if err != nil { 273 panic(err) 274 } 275 276 var ( 277 reg = b & low_6_offset 278 offset, _ = util.DecodeULEB128(frame.buf) 279 ) 280 281 frame.Regs[uint64(reg)] = DWRule{Offset: int64(offset) * frame.dataAlignment, Rule: RuleOffset} 282 } 283 284 func restore(frame *FrameContext) { 285 b, err := frame.buf.ReadByte() 286 if err != nil { 287 panic(err) 288 } 289 290 reg := uint64(b & low_6_offset) 291 oldrule, ok := frame.initialRegs[reg] 292 if ok { 293 frame.Regs[reg] = DWRule{Offset: oldrule.Offset, Rule: RuleOffset} 294 } else { 295 frame.Regs[reg] = DWRule{Rule: RuleUndefined} 296 } 297 } 298 299 func setloc(frame *FrameContext) { 300 var loc uint64 301 binary.Read(frame.buf, frame.order, &loc) 302 303 frame.loc = loc + frame.cie.staticBase 304 } 305 306 func offsetextended(frame *FrameContext) { 307 var ( 308 reg, _ = util.DecodeULEB128(frame.buf) 309 offset, _ = util.DecodeULEB128(frame.buf) 310 ) 311 312 frame.Regs[reg] = DWRule{Offset: int64(offset) * frame.dataAlignment, Rule: RuleOffset} 313 } 314 315 func undefined(frame *FrameContext) { 316 reg, _ := util.DecodeULEB128(frame.buf) 317 frame.Regs[reg] = DWRule{Rule: RuleUndefined} 318 } 319 320 func samevalue(frame *FrameContext) { 321 reg, _ := util.DecodeULEB128(frame.buf) 322 frame.Regs[reg] = DWRule{Rule: RuleSameVal} 323 } 324 325 func register(frame *FrameContext) { 326 reg1, _ := util.DecodeULEB128(frame.buf) 327 reg2, _ := util.DecodeULEB128(frame.buf) 328 frame.Regs[reg1] = DWRule{Reg: reg2, Rule: RuleRegister} 329 } 330 331 func rememberstate(frame *FrameContext) { 332 frame.prevRegs = frame.Regs 333 } 334 335 func restorestate(frame *FrameContext) { 336 frame.Regs = frame.prevRegs 337 } 338 339 func restoreextended(frame *FrameContext) { 340 reg, _ := util.DecodeULEB128(frame.buf) 341 342 oldrule, ok := frame.initialRegs[reg] 343 if ok { 344 frame.Regs[reg] = DWRule{Offset: oldrule.Offset, Rule: RuleOffset} 345 } else { 346 frame.Regs[reg] = DWRule{Rule: RuleUndefined} 347 } 348 } 349 350 func defcfa(frame *FrameContext) { 351 reg, _ := util.DecodeULEB128(frame.buf) 352 offset, _ := util.DecodeULEB128(frame.buf) 353 354 frame.CFA.Rule = RuleCFA 355 frame.CFA.Reg = reg 356 frame.CFA.Offset = int64(offset) 357 } 358 359 func defcfaregister(frame *FrameContext) { 360 reg, _ := util.DecodeULEB128(frame.buf) 361 frame.CFA.Reg = reg 362 } 363 364 func defcfaoffset(frame *FrameContext) { 365 offset, _ := util.DecodeULEB128(frame.buf) 366 frame.CFA.Offset = int64(offset) 367 } 368 369 func defcfasf(frame *FrameContext) { 370 reg, _ := util.DecodeULEB128(frame.buf) 371 offset, _ := util.DecodeSLEB128(frame.buf) 372 373 frame.CFA.Rule = RuleCFA 374 frame.CFA.Reg = reg 375 frame.CFA.Offset = offset * frame.dataAlignment 376 } 377 378 func defcfaoffsetsf(frame *FrameContext) { 379 offset, _ := util.DecodeSLEB128(frame.buf) 380 offset *= frame.dataAlignment 381 frame.CFA.Offset = offset 382 } 383 384 func defcfaexpression(frame *FrameContext) { 385 var ( 386 l, _ = util.DecodeULEB128(frame.buf) 387 expr = frame.buf.Next(int(l)) 388 ) 389 390 frame.CFA.Expression = expr 391 frame.CFA.Rule = RuleExpression 392 } 393 394 func expression(frame *FrameContext) { 395 var ( 396 reg, _ = util.DecodeULEB128(frame.buf) 397 l, _ = util.DecodeULEB128(frame.buf) 398 expr = frame.buf.Next(int(l)) 399 ) 400 401 frame.Regs[reg] = DWRule{Rule: RuleExpression, Expression: expr} 402 } 403 404 func offsetextendedsf(frame *FrameContext) { 405 var ( 406 reg, _ = util.DecodeULEB128(frame.buf) 407 offset, _ = util.DecodeSLEB128(frame.buf) 408 ) 409 410 frame.Regs[reg] = DWRule{Offset: offset * frame.dataAlignment, Rule: RuleOffset} 411 } 412 413 func valoffset(frame *FrameContext) { 414 var ( 415 reg, _ = util.DecodeULEB128(frame.buf) 416 offset, _ = util.DecodeULEB128(frame.buf) 417 ) 418 419 frame.Regs[reg] = DWRule{Offset: int64(offset), Rule: RuleValOffset} 420 } 421 422 func valoffsetsf(frame *FrameContext) { 423 var ( 424 reg, _ = util.DecodeULEB128(frame.buf) 425 offset, _ = util.DecodeSLEB128(frame.buf) 426 ) 427 428 frame.Regs[reg] = DWRule{Offset: offset * frame.dataAlignment, Rule: RuleValOffset} 429 } 430 431 func valexpression(frame *FrameContext) { 432 var ( 433 reg, _ = util.DecodeULEB128(frame.buf) 434 l, _ = util.DecodeULEB128(frame.buf) 435 expr = frame.buf.Next(int(l)) 436 ) 437 438 frame.Regs[reg] = DWRule{Rule: RuleValExpression, Expression: expr} 439 } 440 441 func louser(frame *FrameContext) { 442 frame.buf.Next(1) 443 } 444 445 func hiuser(frame *FrameContext) { 446 frame.buf.Next(1) 447 }