Index: llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h @@ -69,8 +69,9 @@ /// Extracts an address-sized value and applies a relocation to the result if /// one exists for the given offset. - uint64_t getRelocatedAddress(uint64_t *Off, uint64_t *SecIx = nullptr) const { - return getRelocatedValue(getAddressSize(), Off, SecIx); + uint64_t getRelocatedAddress(uint64_t *Off, uint64_t *SecIx = nullptr, + Error *Err = nullptr) const { + return getRelocatedValue(getAddressSize(), Off, SecIx, Err); } uint64_t getRelocatedAddress(Cursor &C, uint64_t *SecIx = nullptr) const { return getRelocatedValue(getAddressSize(), &getOffset(C), SecIx, Index: llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -36,8 +36,10 @@ Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset) { - while (*Offset < EndOffset) { - uint8_t Opcode = Data.getRelocatedValue(1, Offset); + Error Err = Error::success(); + while (!Err && *Offset < EndOffset) { + uint8_t Opcode = + Data.getRelocatedValue(1, Offset, /*SectionIndex =*/nullptr, &Err); // Some instructions have a primary opcode encoded in the top bits. uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK; @@ -55,7 +57,7 @@ addInstruction(Primary, Op1); break; case DW_CFA_offset: - addInstruction(Primary, Op1, Data.getULEB128(Offset)); + addInstruction(Primary, Op1, Data.getULEB128(Offset, &Err)); break; } } else { @@ -74,19 +76,23 @@ break; case DW_CFA_set_loc: // Operands: Address - addInstruction(Opcode, Data.getRelocatedAddress(Offset)); + addInstruction(Opcode, Data.getRelocatedAddress( + Offset, /*SectionIndex =*/nullptr, &Err)); break; case DW_CFA_advance_loc1: // Operands: 1-byte delta - addInstruction(Opcode, Data.getRelocatedValue(1, Offset)); + addInstruction(Opcode, Data.getRelocatedValue( + 1, Offset, /*SectionIndex =*/nullptr, &Err)); break; case DW_CFA_advance_loc2: // Operands: 2-byte delta - addInstruction(Opcode, Data.getRelocatedValue(2, Offset)); + addInstruction(Opcode, Data.getRelocatedValue( + 2, Offset, /*SectionIndex =*/nullptr, &Err)); break; case DW_CFA_advance_loc4: // Operands: 4-byte delta - addInstruction(Opcode, Data.getRelocatedValue(4, Offset)); + addInstruction(Opcode, Data.getRelocatedValue( + 4, Offset, /*SectionIndex =*/nullptr, &Err)); break; case DW_CFA_restore_extended: case DW_CFA_undefined: @@ -95,11 +101,11 @@ case DW_CFA_def_cfa_offset: case DW_CFA_GNU_args_size: // Operands: ULEB128 - addInstruction(Opcode, Data.getULEB128(Offset)); + addInstruction(Opcode, Data.getULEB128(Offset, &Err)); break; case DW_CFA_def_cfa_offset_sf: // Operands: SLEB128 - addInstruction(Opcode, Data.getSLEB128(Offset)); + addInstruction(Opcode, Data.getSLEB128(Offset, &Err)); break; case DW_CFA_offset_extended: case DW_CFA_register: @@ -109,8 +115,8 @@ // Note: We can not embed getULEB128 directly into function // argument list. getULEB128 changes Offset and order of evaluation // for arguments is unspecified. - auto op1 = Data.getULEB128(Offset); - auto op2 = Data.getULEB128(Offset); + auto op1 = Data.getULEB128(Offset, &Err); + auto op2 = Data.getULEB128(Offset, &Err); addInstruction(Opcode, op1, op2); break; } @@ -119,13 +125,13 @@ case DW_CFA_val_offset_sf: { // Operands: ULEB128, SLEB128 // Note: see comment for the previous case - auto op1 = Data.getULEB128(Offset); - auto op2 = (uint64_t)Data.getSLEB128(Offset); + auto op1 = Data.getULEB128(Offset, &Err); + auto op2 = (uint64_t)Data.getSLEB128(Offset, &Err); addInstruction(Opcode, op1, op2); break; } case DW_CFA_def_cfa_expression: { - uint32_t ExprLength = Data.getULEB128(Offset); + uint32_t ExprLength = Data.getULEB128(Offset, &Err); addInstruction(Opcode, 0); DataExtractor Extractor( Data.getData().slice(*Offset, *Offset + ExprLength), @@ -140,8 +146,8 @@ } case DW_CFA_expression: case DW_CFA_val_expression: { - auto RegNum = Data.getULEB128(Offset); - auto BlockLength = Data.getULEB128(Offset); + auto RegNum = Data.getULEB128(Offset, &Err); + auto BlockLength = Data.getULEB128(Offset, &Err); addInstruction(Opcode, RegNum, 0); DataExtractor Extractor( Data.getData().slice(*Offset, *Offset + BlockLength), @@ -158,7 +164,7 @@ } } - return Error::success(); + return Err; } namespace { Index: llvm/test/DebugInfo/X86/eh-frame-truncated-cfi.s =================================================================== --- /dev/null +++ llvm/test/DebugInfo/X86/eh-frame-truncated-cfi.s @@ -0,0 +1,19 @@ +## Check we report a proper error when the content of the .eh_frame section +## is truncated so that the initial instructions are can't be read. + +# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t +# RUN: not llvm-dwarfdump -debug-frame %t 2>&1 | FileCheck %s + +# CHECK: .eh_frame contents: +# CHECK: error: unexpected end of data at offset 0xd while reading [0xd, 0xe) + +.section .eh_frame,"a",@unwind + .long 0xff ## Length + .long 0x00000000 ## CIE ID + .byte 1 ## Version + .byte 0 ## Code Alignment Factor + .byte 0 ## Data Alignment Factor + .byte 0 ## Augmentation Length + .byte 0 ## Return Address Register +## The set of Call Frame Instructions is supposed to be here, +## but it is missing.