1 //===-- DWARFFormValue.cpp --------------------------------------*- C++ -*-===// 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 <assert.h> 11 12 #include "lldb/Core/dwarf.h" 13 #include "lldb/Core/Stream.h" 14 15 #include "DWARFFormValue.h" 16 #include "DWARFCompileUnit.h" 17 18 class DWARFCompileUnit; 19 20 using namespace lldb_private; 21 22 23 static uint8_t g_form_sizes_addr4[] = 24 { 25 0, // 0x00 unused 26 4, // 0x01 DW_FORM_addr 27 0, // 0x02 unused 28 0, // 0x03 DW_FORM_block2 29 0, // 0x04 DW_FORM_block4 30 2, // 0x05 DW_FORM_data2 31 4, // 0x06 DW_FORM_data4 32 8, // 0x07 DW_FORM_data8 33 0, // 0x08 DW_FORM_string 34 0, // 0x09 DW_FORM_block 35 0, // 0x0a DW_FORM_block1 36 1, // 0x0b DW_FORM_data1 37 1, // 0x0c DW_FORM_flag 38 0, // 0x0d DW_FORM_sdata 39 4, // 0x0e DW_FORM_strp 40 0, // 0x0f DW_FORM_udata 41 4, // 0x10 DW_FORM_ref_addr 42 1, // 0x11 DW_FORM_ref1 43 2, // 0x12 DW_FORM_ref2 44 4, // 0x13 DW_FORM_ref4 45 8, // 0x14 DW_FORM_ref8 46 0, // 0x15 DW_FORM_ref_udata 47 0, // 0x16 DW_FORM_indirect 48 }; 49 50 static uint8_t 51 g_form_sizes_addr8[] = 52 { 53 0, // 0x00 unused 54 8, // 0x01 DW_FORM_addr 55 0, // 0x02 unused 56 0, // 0x03 DW_FORM_block2 57 0, // 0x04 DW_FORM_block4 58 2, // 0x05 DW_FORM_data2 59 4, // 0x06 DW_FORM_data4 60 8, // 0x07 DW_FORM_data8 61 0, // 0x08 DW_FORM_string 62 0, // 0x09 DW_FORM_block 63 0, // 0x0a DW_FORM_block1 64 1, // 0x0b DW_FORM_data1 65 1, // 0x0c DW_FORM_flag 66 0, // 0x0d DW_FORM_sdata 67 4, // 0x0e DW_FORM_strp 68 0, // 0x0f DW_FORM_udata 69 8, // 0x10 DW_FORM_ref_addr 70 1, // 0x11 DW_FORM_ref1 71 2, // 0x12 DW_FORM_ref2 72 4, // 0x13 DW_FORM_ref4 73 8, // 0x14 DW_FORM_ref8 74 0, // 0x15 DW_FORM_ref_udata 75 0, // 0x16 DW_FORM_indirect 76 }; 77 78 const uint8_t * 79 DWARFFormValue::GetFixedFormSizesForAddressSize (uint8_t addr_size) 80 { 81 switch (addr_size) 82 { 83 case 4: return g_form_sizes_addr4; 84 case 8: return g_form_sizes_addr8; 85 } 86 return NULL; 87 } 88 89 DWARFFormValue::DWARFFormValue(dw_form_t form) : 90 m_form(form), 91 m_value() 92 { 93 } 94 95 bool 96 DWARFFormValue::ExtractValue(const DataExtractor& data, uint32_t* offset_ptr, const DWARFCompileUnit* cu) 97 { 98 bool indirect = false; 99 bool is_block = false; 100 m_value.data = NULL; 101 // Read the value for the form into value and follow and DW_FORM_indirect instances we run into 102 do 103 { 104 indirect = false; 105 switch (m_form) 106 { 107 case DW_FORM_addr: m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu)); break; 108 case DW_FORM_block2: m_value.value.uval = data.GetU16(offset_ptr); is_block = true; break; 109 case DW_FORM_block4: m_value.value.uval = data.GetU32(offset_ptr); is_block = true; break; 110 case DW_FORM_data2: m_value.value.uval = data.GetU16(offset_ptr); break; 111 case DW_FORM_data4: m_value.value.uval = data.GetU32(offset_ptr); break; 112 case DW_FORM_data8: m_value.value.uval = data.GetU64(offset_ptr); break; 113 case DW_FORM_string: m_value.value.cstr = data.GetCStr(offset_ptr); 114 // Set the string value to also be the data for inlined cstr form values only 115 // so we can tell the differnence between DW_FORM_string and DW_FORM_strp form 116 // values; 117 m_value.data = (uint8_t*)m_value.value.cstr; break; 118 case DW_FORM_block: m_value.value.uval = data.GetULEB128(offset_ptr); is_block = true; break; 119 case DW_FORM_block1: m_value.value.uval = data.GetU8(offset_ptr); is_block = true; break; 120 case DW_FORM_data1: m_value.value.uval = data.GetU8(offset_ptr); break; 121 case DW_FORM_flag: m_value.value.uval = data.GetU8(offset_ptr); break; 122 case DW_FORM_sdata: m_value.value.sval = data.GetSLEB128(offset_ptr); break; 123 case DW_FORM_strp: m_value.value.uval = data.GetU32(offset_ptr); break; 124 // case DW_FORM_APPLE_db_str: 125 case DW_FORM_udata: m_value.value.uval = data.GetULEB128(offset_ptr); break; 126 case DW_FORM_ref_addr: m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu)); break; 127 case DW_FORM_ref1: m_value.value.uval = data.GetU8(offset_ptr); break; 128 case DW_FORM_ref2: m_value.value.uval = data.GetU16(offset_ptr); break; 129 case DW_FORM_ref4: m_value.value.uval = data.GetU32(offset_ptr); break; 130 case DW_FORM_ref8: m_value.value.uval = data.GetU64(offset_ptr); break; 131 case DW_FORM_ref_udata: m_value.value.uval = data.GetULEB128(offset_ptr); break; 132 case DW_FORM_indirect: 133 m_form = data.GetULEB128(offset_ptr); 134 indirect = true; 135 break; 136 137 default: 138 return false; 139 break; 140 } 141 } while (indirect); 142 143 if (is_block) 144 { 145 m_value.data = data.PeekData(*offset_ptr, m_value.value.uval); 146 if (m_value.data != NULL) 147 { 148 *offset_ptr += m_value.value.uval; 149 } 150 } 151 152 return true; 153 } 154 155 bool 156 DWARFFormValue::SkipValue(const DataExtractor& debug_info_data, uint32_t* offset_ptr, const DWARFCompileUnit* cu) const 157 { 158 return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, cu); 159 } 160 161 bool 162 DWARFFormValue::SkipValue(dw_form_t form, const DataExtractor& debug_info_data, uint32_t* offset_ptr, const DWARFCompileUnit* cu) 163 { 164 bool indirect = false; 165 do 166 { 167 indirect = false; 168 switch (form) 169 { 170 // Blocks if inlined data that have a length field and the data bytes 171 // inlined in the .debug_info 172 case DW_FORM_block : { dw_uleb128_t size = debug_info_data.GetULEB128(offset_ptr); *offset_ptr += size; } return true; 173 case DW_FORM_block1 : { dw_uleb128_t size = debug_info_data.GetU8(offset_ptr); *offset_ptr += size; } return true; 174 case DW_FORM_block2 : { dw_uleb128_t size = debug_info_data.GetU16(offset_ptr); *offset_ptr += size; } return true; 175 case DW_FORM_block4 : { dw_uleb128_t size = debug_info_data.GetU32(offset_ptr); *offset_ptr += size; } return true; 176 177 // Inlined NULL terminated C-strings 178 case DW_FORM_string : 179 debug_info_data.GetCStr(offset_ptr); 180 return true; 181 182 // Compile unit address sized values 183 case DW_FORM_addr : 184 case DW_FORM_ref_addr : 185 *offset_ptr += DWARFCompileUnit::GetAddressByteSize(cu); 186 return true; 187 188 // 1 byte values 189 case DW_FORM_data1 : 190 case DW_FORM_flag : 191 case DW_FORM_ref1 : 192 *offset_ptr += 1; 193 return true; 194 195 // 2 byte values 196 case DW_FORM_data2 : 197 case DW_FORM_ref2 : 198 *offset_ptr += 2; 199 return true; 200 201 // 4 byte values 202 case DW_FORM_strp : 203 case DW_FORM_data4 : 204 case DW_FORM_ref4 : 205 *offset_ptr += 4; 206 return true; 207 208 // 8 byte values 209 case DW_FORM_data8 : 210 case DW_FORM_ref8 : 211 *offset_ptr += 8; 212 return true; 213 214 // signed or unsigned LEB 128 values 215 // case DW_FORM_APPLE_db_str: 216 case DW_FORM_sdata : 217 case DW_FORM_udata : 218 case DW_FORM_ref_udata : 219 debug_info_data.Skip_LEB128(offset_ptr); 220 return true; 221 222 case DW_FORM_indirect : 223 indirect = true; 224 form = debug_info_data.GetULEB128(offset_ptr); 225 break; 226 default: 227 return false; 228 } 229 } while (indirect); 230 return true; 231 } 232 233 //bool 234 //DWARFFormValue::PutUnsigned(dw_form_t form, dw_offset_t offset, uint64_t value, BinaryStreamBuf& out_buff, const DWARFCompileUnit* cu, bool fixup_cu_relative_refs) 235 //{ 236 // assert(offset != DW_INVALID_OFFSET); 237 //// printf("PutUnsigned(%s, 0x%8.8x, 0x%16.16llx, %d)\n", DW_FORM_value_to_name(form), offset, value, fixup_cu_relative_refs); 238 // // Read the value for the form into value and follow and DW_FORM_indirect instances we run into 239 // switch (form) 240 // { 241 // case DW_FORM_addr: offset = out_buff.PutMax64(offset, value, DWARFCompileUnit::GetAddressByteSize(cu)); break; 242 // 243 // case DW_FORM_flag: 244 // case DW_FORM_data1: offset = out_buff.Put8(offset, value); break; 245 // case DW_FORM_data2: offset = out_buff.Put16(offset, value); break; 246 // case DW_FORM_data4: offset = out_buff.Put32(offset, value); break; 247 // case DW_FORM_data8: offset = out_buff.Put64(offset, value); break; 248 //// case DW_FORM_udata: offset = out_buff.Put32_as_ULEB128(offset, value); break; 249 //// case DW_FORM_sdata: offset = out_buff.Put32_as_SLEB128(offset, value); break; 250 // case DW_FORM_strp: offset = out_buff.Put32(offset, value); break; 251 //// case DW_FORM_APPLE_db_str: 252 //// offset = out_buff.Put32_as_ULEB128(offset, value); break; 253 // 254 // case DW_FORM_ref1: 255 // if (fixup_cu_relative_refs) value -= cu->GetOffset(); 256 // offset = out_buff.Put8(offset, value); 257 // break; 258 // case DW_FORM_ref2: 259 // if (fixup_cu_relative_refs) value -= cu->GetOffset(); 260 // offset = out_buff.Put16(offset, value); 261 // break; 262 // case DW_FORM_ref4: 263 // if (fixup_cu_relative_refs) value -= cu->GetOffset(); 264 // offset = out_buff.Put32(offset, value); 265 // break; 266 // case DW_FORM_ref8: 267 // if (fixup_cu_relative_refs) value -= cu->GetOffset(); 268 // offset = out_buff.Put64(offset, value); 269 // break; 270 //// case DW_FORM_ref_udata: 271 //// if (fixup_cu_relative_refs) value -= cu->GetOffset(); 272 //// offset = out_buff.Put32_as_ULEB128(offset, value); 273 //// break; 274 // case DW_FORM_ref_addr: 275 // // TODO: Add support for DWARF3 if we ever start emitting DWARF3. The DW_FORM_ref_addr 276 // // is always the same size as an address prior to DWARF3, and with DWARF3 or later it 277 // // is 4 hard coded to bytes. 278 // offset = out_buff.PutMax64(offset, value, DWARFCompileUnit::GetAddressByteSize(cu)); 279 // break; 280 // 281 // default: 282 // return false; 283 // } 284 // 285 // return true; 286 //} 287 288 //bool 289 //DWARFFormValue::TransferValue(dw_form_t form, const DataExtractor& data, uint32_t* offset_ptr, const DWARFCompileUnit* cu, BinaryStreamBuf& out_buff) 290 //{ 291 // DWARFFormValue formValue(form); 292 // if (formValue.ExtractValue(data, offset_ptr,cu)) 293 // return TransferValue(formValue, cu, out_buff); 294 // return false; 295 //} 296 297 //bool 298 //DWARFFormValue::TransferValue(const DWARFFormValue& formValue, const DWARFCompileUnit* cu, BinaryStreamBuf& out_buff) 299 //{ 300 // // Read the value for the form into value and follow and DW_FORM_indirect instances we run into 301 // dw_form_t form = formValue.Form(); 302 // switch (form) 303 // { 304 // case DW_FORM_addr: 305 // case DW_FORM_ref_addr: 306 // { 307 // uint8_t addr_size = DWARFCompileUnit::GetAddressByteSize(cu); 308 // out_buff.AppendMax64(formValue.Unsigned(), addr_size); 309 // } 310 // break; 311 // 312 // case DW_FORM_block: out_buff.Append32_as_ULEB128(formValue.Unsigned()); break; 313 // case DW_FORM_block1: out_buff.Append8(formValue.Unsigned()); break; 314 // case DW_FORM_block2: out_buff.Append16(formValue.Unsigned()); break; 315 // case DW_FORM_block4: out_buff.Append32(formValue.Unsigned()); break; 316 // 317 // case DW_FORM_flag: 318 // case DW_FORM_data1: out_buff.Append8(formValue.Unsigned()); break; 319 // case DW_FORM_data2: out_buff.Append16(formValue.Unsigned()); break; 320 // case DW_FORM_data4: out_buff.Append32(formValue.Unsigned()); break; 321 // case DW_FORM_data8: out_buff.Append64(formValue.Unsigned()); break; 322 // case DW_FORM_udata: out_buff.Append32_as_ULEB128(formValue.Unsigned()); break; 323 // case DW_FORM_sdata: out_buff.Append32_as_SLEB128(formValue.Signed()); break; 324 // 325 // case DW_FORM_string: out_buff.AppendCStr(formValue.m_value.value.cstr); break; 326 // case DW_FORM_strp: out_buff.Append32(formValue.Unsigned()); break; 327 //// case DW_FORM_APPLE_db_str: 328 //// out_buff.Append32_as_ULEB128(formValue.Unsigned()); break; 329 // 330 // case DW_FORM_ref1: out_buff.Append8(formValue.Unsigned()); break; 331 // case DW_FORM_ref2: out_buff.Append16(formValue.Unsigned()); break; 332 // case DW_FORM_ref4: out_buff.Append32(formValue.Unsigned()); break; 333 // case DW_FORM_ref8: out_buff.Append64(formValue.Unsigned()); break; 334 // case DW_FORM_ref_udata: out_buff.Append32_as_ULEB128(formValue.Unsigned()); break; 335 // 336 // case DW_FORM_indirect: 337 // assert(!"DW_FORM_indirect found in DWARFFormValue::TransferValue() for an extracted form..."); 338 // break; 339 // 340 // default: 341 // Log::Error("DWARFFormValue::TransferValue() Unrecognized form: 0x%4.4x", form); 342 // return false; 343 // break; 344 // } 345 // 346 // const uint8_t* block_data = formValue.BlockData(); 347 // if (block_data) 348 // out_buff.AppendData(block_data, formValue.Unsigned()); 349 // return true; 350 //} 351 352 void 353 DWARFFormValue::Dump(Stream *s, const DataExtractor* debug_str_data, const DWARFCompileUnit* cu) const 354 { 355 uint64_t uvalue = Unsigned(); 356 bool cu_relative_offset = false; 357 358 bool verbose = s->GetVerbose(); 359 360 switch (m_form) 361 { 362 case DW_FORM_addr: s->Address(uvalue, sizeof (uint64_t)); break; 363 case DW_FORM_flag: 364 case DW_FORM_data1: s->PutHex8(uvalue); break; 365 case DW_FORM_data2: s->PutHex16(uvalue); break; 366 case DW_FORM_data4: s->PutHex32(uvalue); break; 367 case DW_FORM_data8: s->PutHex64(uvalue); break; 368 case DW_FORM_string: s->QuotedCString(AsCString(NULL)); break; 369 case DW_FORM_block: 370 case DW_FORM_block1: 371 case DW_FORM_block2: 372 case DW_FORM_block4: 373 if (uvalue > 0) 374 { 375 switch (m_form) 376 { 377 case DW_FORM_block: s->Printf("<0x%llx> ", uvalue); break; 378 case DW_FORM_block1: s->Printf("<0x%2.2x> ", (uint8_t)uvalue); break; 379 case DW_FORM_block2: s->Printf("<0x%4.4x> ", (uint16_t)uvalue); break; 380 case DW_FORM_block4: s->Printf("<0x%8.8x> ", (uint32_t)uvalue); break; 381 default: break; 382 } 383 384 const uint8_t* data_ptr = m_value.data; 385 if (data_ptr) 386 { 387 const uint8_t* end_data_ptr = data_ptr + uvalue; // uvalue contains size of block 388 while (data_ptr < end_data_ptr) 389 { 390 s->Printf("%2.2x ", *data_ptr); 391 ++data_ptr; 392 } 393 } 394 else 395 s->PutCString("NULL"); 396 } 397 break; 398 399 case DW_FORM_sdata: s->PutSLEB128(uvalue); break; 400 case DW_FORM_udata: s->PutULEB128(uvalue); break; 401 case DW_FORM_strp: 402 if (debug_str_data) 403 { 404 if (verbose) 405 s->Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); 406 407 const char* dbg_str = AsCString(debug_str_data); 408 if (dbg_str) 409 s->QuotedCString(dbg_str); 410 } 411 else 412 { 413 s->PutHex32(uvalue); 414 } 415 break; 416 417 case DW_FORM_ref_addr: 418 { 419 s->Address(uvalue, sizeof (uint64_t) * 2); 420 break; 421 } 422 case DW_FORM_ref1: cu_relative_offset = true; if (verbose) s->Printf("cu + 0x%2.2x", (uint8_t)uvalue); break; 423 case DW_FORM_ref2: cu_relative_offset = true; if (verbose) s->Printf("cu + 0x%4.4x", (uint16_t)uvalue); break; 424 case DW_FORM_ref4: cu_relative_offset = true; if (verbose) s->Printf("cu + 0x%4.4x", (uint32_t)uvalue); break; 425 case DW_FORM_ref8: cu_relative_offset = true; if (verbose) s->Printf("cu + 0x%8.8llx", uvalue); break; 426 case DW_FORM_ref_udata: cu_relative_offset = true; if (verbose) s->Printf("cu + 0x%llx", uvalue); break; 427 428 // All DW_FORM_indirect attributes should be resolved prior to calling this function 429 case DW_FORM_indirect: s->PutCString("DW_FORM_indirect"); break; 430 default: 431 s->Printf("DW_FORM(0x%4.4x)", m_form); 432 break; 433 } 434 435 if (cu_relative_offset) 436 { 437 if (verbose) 438 s->PutCString(" => "); 439 440 s->Printf("{0x%8.8x}", (uvalue + (cu ? cu->GetOffset() : 0))); 441 } 442 } 443 444 const char* 445 DWARFFormValue::AsCString(const DataExtractor* debug_str_data_ptr) const 446 { 447 if (IsInlinedCStr()) 448 return m_value.value.cstr; 449 else if (debug_str_data_ptr) 450 return debug_str_data_ptr->PeekCStr(m_value.value.uval); 451 return NULL; 452 } 453 454 uint64_t 455 DWARFFormValue::Reference(const DWARFCompileUnit* cu) const 456 { 457 uint64_t die_offset = m_value.value.uval; 458 switch (m_form) 459 { 460 case DW_FORM_ref1: 461 case DW_FORM_ref2: 462 case DW_FORM_ref4: 463 case DW_FORM_ref8: 464 case DW_FORM_ref_udata: 465 die_offset += (cu ? cu->GetOffset() : 0); 466 break; 467 468 default: 469 break; 470 } 471 472 return die_offset; 473 } 474 475 //---------------------------------------------------------------------- 476 // Resolve any compile unit specific references so that we don't need 477 // the compile unit at a later time in order to work with the form 478 // value. 479 //---------------------------------------------------------------------- 480 bool 481 DWARFFormValue::ResolveCompileUnitReferences(const DWARFCompileUnit* cu) 482 { 483 switch (m_form) 484 { 485 case DW_FORM_ref1: 486 case DW_FORM_ref2: 487 case DW_FORM_ref4: 488 case DW_FORM_ref8: 489 case DW_FORM_ref_udata: 490 m_value.value.uval += cu->GetOffset(); 491 m_form = DW_FORM_ref_addr; 492 return true; 493 break; 494 495 default: 496 break; 497 } 498 499 return false; 500 } 501 502 const uint8_t* 503 DWARFFormValue::BlockData() const 504 { 505 if (!IsInlinedCStr()) 506 return m_value.data; 507 return NULL; 508 } 509 510 511 bool 512 DWARFFormValue::IsBlockForm(const dw_form_t form) 513 { 514 switch (form) 515 { 516 case DW_FORM_block: 517 case DW_FORM_block1: 518 case DW_FORM_block2: 519 case DW_FORM_block4: 520 return true; 521 } 522 return false; 523 } 524 525 bool 526 DWARFFormValue::IsDataForm(const dw_form_t form) 527 { 528 switch (form) 529 { 530 case DW_FORM_sdata: 531 case DW_FORM_udata: 532 case DW_FORM_data1: 533 case DW_FORM_data2: 534 case DW_FORM_data4: 535 case DW_FORM_data8: 536 return true; 537 } 538 return false; 539 } 540 541 int 542 DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const DataExtractor* debug_str_data_ptr) 543 { 544 dw_form_t a_form = a_value.Form(); 545 dw_form_t b_form = b_value.Form(); 546 if (a_form < b_form) 547 return -1; 548 if (a_form > b_form) 549 return 1; 550 switch (a_form) 551 { 552 case DW_FORM_addr: 553 case DW_FORM_flag: 554 case DW_FORM_data1: 555 case DW_FORM_data2: 556 case DW_FORM_data4: 557 case DW_FORM_data8: 558 case DW_FORM_udata: 559 case DW_FORM_ref_addr: 560 { 561 uint64_t a = a_value.Unsigned(); 562 uint64_t b = b_value.Unsigned(); 563 if (a < b) 564 return -1; 565 if (a > b) 566 return 1; 567 return 0; 568 } 569 570 case DW_FORM_sdata: 571 { 572 int64_t a = a_value.Signed(); 573 int64_t b = b_value.Signed(); 574 if (a < b) 575 return -1; 576 if (a > b) 577 return 1; 578 return 0; 579 } 580 581 case DW_FORM_string: 582 case DW_FORM_strp: 583 { 584 const char *a_string = a_value.AsCString(debug_str_data_ptr); 585 const char *b_string = b_value.AsCString(debug_str_data_ptr); 586 if (a_string == b_string) 587 return 0; 588 else if (a_string && b_string) 589 return strcmp(a_string, b_string); 590 else if (a_string == NULL) 591 return -1; // A string is NULL, and B is valid 592 else 593 return 1; // A string valid, and B is NULL 594 } 595 596 597 case DW_FORM_block: 598 case DW_FORM_block1: 599 case DW_FORM_block2: 600 case DW_FORM_block4: 601 { 602 uint64_t a_len = a_value.Unsigned(); 603 uint64_t b_len = b_value.Unsigned(); 604 if (a_len < b_len) 605 return -1; 606 if (a_len > b_len) 607 return 1; 608 // The block lengths are the same 609 return memcmp(a_value.BlockData(), b_value.BlockData(), a_value.Unsigned()); 610 } 611 break; 612 613 case DW_FORM_ref1: 614 case DW_FORM_ref2: 615 case DW_FORM_ref4: 616 case DW_FORM_ref8: 617 case DW_FORM_ref_udata: 618 { 619 uint64_t a = a_value.Reference(a_cu); 620 uint64_t b = b_value.Reference(b_cu); 621 if (a < b) 622 return -1; 623 if (a > b) 624 return 1; 625 return 0; 626 } 627 628 case DW_FORM_indirect: 629 assert(!"This shouldn't happen after the form has been extracted..."); 630 break; 631 632 default: 633 assert(!"Unhandled DW_FORM"); 634 break; 635 } 636 return -1; 637 } 638 639