Skip to content

Commit

Permalink
[DWP] add overflow check for llvm-dwp tools if offset overflow
Browse files Browse the repository at this point in the history
Now, if the offset overflow happens, we just silently ignore it.
We will generate a bad dwp file, which will crash the gdb or make
it undefined behavior, and hard to address the root cause. So, we
need to produce some messages if overflow happens.

Reviewed By: ayermolo, dblaikie, steven.zhang

Differential Revision: https://reviews.llvm.org/D144565
  • Loading branch information
zhuna authored and qshanz373 committed Jun 1, 2023
1 parent e79fac2 commit 53a483c
Show file tree
Hide file tree
Showing 11 changed files with 966 additions and 21 deletions.
3 changes: 2 additions & 1 deletion llvm/include/llvm/DWP/DWP.h
Expand Up @@ -60,7 +60,8 @@ struct CompileUnitIdentifiers {
const char *DWOName = "";
};

Error write(MCStreamer &Out, ArrayRef<std::string> Inputs);
Error write(MCStreamer &Out, ArrayRef<std::string> Inputs,
bool ContinueOnCuIndexOverflow);

unsigned getContributionIndex(DWARFSectionKind Kind, uint32_t IndexVersion);

Expand Down
91 changes: 72 additions & 19 deletions llvm/lib/DWP/DWP.cpp
Expand Up @@ -11,12 +11,14 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/DWP/DWP.h"
#include "llvm/ADT/Twine.h"
#include "llvm/DWP/DWPError.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
#include "llvm/Object/Decompressor.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include <limits>

Expand Down Expand Up @@ -178,12 +180,28 @@ static StringRef getSubsection(StringRef Section,
return Section.substr(Off->getOffset(), Off->getLength());
}

static void
addAllTypesFromDWP(MCStreamer &Out,
MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
const DWARFUnitIndex &TUIndex, MCSection *OutputTypes,
StringRef Types, const UnitIndexEntry &TUEntry,
uint32_t &TypesOffset, unsigned TypesContributionIndex) {
static Error sectionOverflowErrorOrWarning(uint32_t PrevOffset,
uint32_t OverflowedOffset,
StringRef SectionName,
bool ContinueOnCuIndexOverflow) {
std::string Msg =
(SectionName +
Twine(" Section Contribution Offset overflow 4G. Previous Offset ") +
Twine(PrevOffset) + Twine(", After overflow offset ") +
Twine(OverflowedOffset) + Twine("."))
.str();
if (ContinueOnCuIndexOverflow) {
WithColor::defaultWarningHandler(make_error<DWPError>(Msg));
return Error::success();
}
return make_error<DWPError>(Msg);
}

static Error addAllTypesFromDWP(
MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types,
const UnitIndexEntry &TUEntry, uint32_t &TypesOffset,
unsigned TypesContributionIndex, bool ContinueOnCuIndexOverflow) {
Out.switchSection(OutputTypes);
for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) {
auto *I = E.getContributions();
Expand All @@ -210,14 +228,23 @@ addAllTypesFromDWP(MCStreamer &Out,
TUEntry.Contributions[TypesContributionIndex].getOffset(),
C.getLength()));
C.setOffset(TypesOffset);
uint32_t OldOffset = TypesOffset;
static_assert(sizeof(OldOffset) == sizeof(TypesOffset));
TypesOffset += C.getLength();
if (OldOffset > TypesOffset) {
if (Error Err = sectionOverflowErrorOrWarning(
OldOffset, TypesOffset, "Types", ContinueOnCuIndexOverflow))
return Err;
}
}
return Error::success();
}

static void addAllTypesFromTypesSection(
static Error addAllTypesFromTypesSection(
MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
MCSection *OutputTypes, const std::vector<StringRef> &TypesSections,
const UnitIndexEntry &CUEntry, uint32_t &TypesOffset) {
const UnitIndexEntry &CUEntry, uint32_t &TypesOffset,
bool ContinueOnCuIndexOverflow) {
for (StringRef Types : TypesSections) {
Out.switchSection(OutputTypes);
uint64_t Offset = 0;
Expand All @@ -243,9 +270,16 @@ static void addAllTypesFromTypesSection(
continue;

Out.emitBytes(Types.substr(PrevOffset, C.getLength32()));
uint32_t OldOffset = TypesOffset;
TypesOffset += C.getLength32();
if (OldOffset > TypesOffset) {
if (Error Err = sectionOverflowErrorOrWarning(
OldOffset, TypesOffset, "types", ContinueOnCuIndexOverflow))
return Err;
}
}
}
return Error::success();
}

static std::string buildDWODescription(StringRef Name, StringRef DWPName,
Expand Down Expand Up @@ -548,7 +582,8 @@ Error handleSection(
return Error::success();
}

Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
Error write(MCStreamer &Out, ArrayRef<std::string> Inputs,
bool ContinueOnCuIndexOverflow) {
const auto &MCOFI = *Out.getContext().getObjectFileInfo();
MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
Expand Down Expand Up @@ -646,7 +681,19 @@ Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
auto Index = getContributionIndex(Pair.first, IndexVersion);
CurEntry.Contributions[Index].setOffset(ContributionOffsets[Index]);
CurEntry.Contributions[Index].setLength(Pair.second);
uint32_t OldOffset = ContributionOffsets[Index];
ContributionOffsets[Index] += CurEntry.Contributions[Index].getLength32();
if (OldOffset > ContributionOffsets[Index]) {
uint32_t SectionIndex = 0;
for (auto &Section : Obj.sections()) {
if (SectionIndex == Index) {
return sectionOverflowErrorOrWarning(
OldOffset, ContributionOffsets[Index], *Section.getName(),
ContinueOnCuIndexOverflow);
}
++SectionIndex;
}
}
}

uint32_t &InfoSectionOffset =
Expand All @@ -670,9 +717,12 @@ Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
C.setLength(Header.Length + 4);

if (std::numeric_limits<uint32_t>::max() - InfoSectionOffset <
C.getLength32())
return make_error<DWPError>(
"debug information section offset is greater than 4GB");
C.getLength32()) {
if (Error Err = sectionOverflowErrorOrWarning(
InfoSectionOffset, InfoSectionOffset + C.getLength32(),
"debug_info", ContinueOnCuIndexOverflow))
return Err;
}

UnitOffset += C.getLength32();
if (Header.Version < 5 ||
Expand Down Expand Up @@ -709,9 +759,11 @@ Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {

if (IndexVersion == 2) {
// Add types from the .debug_types section from DWARF < 5.
addAllTypesFromTypesSection(
Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry,
ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)]);
if (Error Err = addAllTypesFromTypesSection(
Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry,
ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)],
ContinueOnCuIndexOverflow))
return Err;
}
continue;
}
Expand Down Expand Up @@ -805,10 +857,11 @@ Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {

unsigned TypesContributionIndex =
getContributionIndex(TUSectionKind, IndexVersion);
addAllTypesFromDWP(Out, TypeIndexEntries, TUIndex, OutSection,
TypeInputSection, CurEntry,
ContributionOffsets[TypesContributionIndex],
TypesContributionIndex);
if (Error Err = addAllTypesFromDWP(
Out, TypeIndexEntries, TUIndex, OutSection, TypeInputSection,
CurEntry, ContributionOffsets[TypesContributionIndex],
TypesContributionIndex, ContinueOnCuIndexOverflow))
return Err;
}
}

Expand Down
195 changes: 195 additions & 0 deletions llvm/test/tools/llvm-dwp/Inputs/overflow/debug_info_v4.s
@@ -0,0 +1,195 @@
# Note: This file is compiled from the following code, for
# the purpose of creating an overflowed dwo section.
# After being compiled from source, section `.debug_info.dwo`
# is changed to have length (2^32 - 30) Bytes, and added
# padding with `.fill` directive, so it is likely to
# overflow when packed with other files.
#
# clang -g -S -gsplit-dwarf -gdwarf-4 hello.c
#
# #include <stdio.h>
# void hello() {
# printf("hello\n");
# }

.text
.file "hello.c"
.globl hello # -- Begin function hello
.p2align 4, 0x90
.type hello,@function
hello: # @hello
.Lfunc_begin0:
.file 1 "/xxxxxx/xxxx/xxxxxxxxxx/xxxxxxxx/hello" "hello.c"
.loc 1 3 0 # hello.c:3:0
.cfi_startproc
# %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
.Ltmp0:
.loc 1 4 5 prologue_end # hello.c:4:5
movabsq $.L.str, %rdi
movb $0, %al
callq printf
.loc 1 5 1 # hello.c:5:1
popq %rbp
.cfi_def_cfa %rsp, 8
retq
.Ltmp1:
.Lfunc_end0:
.size hello, .Lfunc_end0-hello
.cfi_endproc
# -- End function
.type .L.str,@object # @.str
.section .rodata.str1.1,"aMS",@progbits,1
.L.str:
.asciz "hello\n"
.size .L.str, 7

.section .debug_abbrev,"",@progbits
.byte 1 # Abbreviation Code
.byte 17 # DW_TAG_compile_unit
.byte 0 # DW_CHILDREN_no
.byte 16 # DW_AT_stmt_list
.byte 23 # DW_FORM_sec_offset
.byte 27 # DW_AT_comp_dir
.byte 14 # DW_FORM_strp
.ascii "\264B" # DW_AT_GNU_pubnames
.byte 25 # DW_FORM_flag_present
.ascii "\260B" # DW_AT_GNU_dwo_name
.byte 14 # DW_FORM_strp
.ascii "\261B" # DW_AT_GNU_dwo_id
.byte 7 # DW_FORM_data8
.byte 17 # DW_AT_low_pc
.byte 1 # DW_FORM_addr
.byte 18 # DW_AT_high_pc
.byte 6 # DW_FORM_data4
.ascii "\263B" # DW_AT_GNU_addr_base
.byte 23 # DW_FORM_sec_offset
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 0 # EOM(3)
.section .debug_info,"",@progbits
.Lcu_begin0:
# .long 4294967295 # 2^32 - 1 #44 # Length of Unit
.long 44 # Length of Unit
.short 4 # DWARF version number
.long .debug_abbrev # Offset Into Abbrev. Section
.byte 8 # Address Size (in bytes)
.byte 1 # Abbrev [1] 0xb:0x25 DW_TAG_compile_unit
.long .Lline_table_start0 # DW_AT_stmt_list
.long .Lskel_string0 # DW_AT_comp_dir
# DW_AT_GNU_pubnames
.long .Lskel_string1 # DW_AT_GNU_dwo_name
.quad -94954012350180462 # DW_AT_GNU_dwo_id
.quad .Lfunc_begin0 # DW_AT_low_pc
.long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
.long .Laddr_table_base0 # DW_AT_GNU_addr_base
# .fill 4294967251 # = 2^32 - 1 - 44
.section .debug_str,"MS",@progbits,1
.Lskel_string0:
.asciz "/xxxxxx/xxxx/xxxxxxxxxx/xxxxxxxx/hello" # string offset=0
.Lskel_string1:
.asciz "hello.dwo" # string offset=39
.section .debug_str.dwo,"eMS",@progbits,1
.Linfo_string0:
.asciz "hello" # string offset=0
.Linfo_string1:
.asciz "clang version 11.1.0 (https://github.com/llvm/llvm-project.git 173544ee3d09cdce8665f2097f677c31e1f1a9a1)" # string offset=6
.Linfo_string2:
.asciz "hello.c" # string offset=111
.Linfo_string3:
.asciz "hello.dwo" # string offset=119
.section .debug_str_offsets.dwo,"e",@progbits
.long 0
.long 6
.long 111
.long 119
.section .debug_info.dwo,"e",@progbits
.long 4294967266 # 2^32 - 30 #33 # Length of Unit
.short 4 # DWARF version number
.long 0 # Offset Into Abbrev. Section
.byte 8 # Address Size (in bytes)
.byte 1 # Abbrev [1] 0xb:0x1a DW_TAG_compile_unit
.byte 1 # DW_AT_producer
.short 12 # DW_AT_language
.byte 2 # DW_AT_name
.byte 3 # DW_AT_GNU_dwo_name
.quad -94954012350180462 # DW_AT_GNU_dwo_id
.byte 2 # Abbrev [2] 0x19:0xb DW_TAG_subprogram
.byte 0 # DW_AT_low_pc
.long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
.byte 1 # DW_AT_frame_base
.byte 86
.byte 0 # DW_AT_name
.byte 1 # DW_AT_decl_file
.byte 3 # DW_AT_decl_line
# DW_AT_external
.byte 0 # End Of Children Mark
.fill 4294967233 # 2^32 - 30 - 33
.section .debug_abbrev.dwo,"e",@progbits
.byte 1 # Abbreviation Code
.byte 17 # DW_TAG_compile_unit
.byte 1 # DW_CHILDREN_yes
.byte 37 # DW_AT_producer
.ascii "\202>" # DW_FORM_GNU_str_index
.byte 19 # DW_AT_language
.byte 5 # DW_FORM_data2
.byte 3 # DW_AT_name
.ascii "\202>" # DW_FORM_GNU_str_index
.ascii "\260B" # DW_AT_GNU_dwo_name
.ascii "\202>" # DW_FORM_GNU_str_index
.ascii "\261B" # DW_AT_GNU_dwo_id
.byte 7 # DW_FORM_data8
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 2 # Abbreviation Code
.byte 46 # DW_TAG_subprogram
.byte 0 # DW_CHILDREN_no
.byte 17 # DW_AT_low_pc
.ascii "\201>" # DW_FORM_GNU_addr_index
.byte 18 # DW_AT_high_pc
.byte 6 # DW_FORM_data4
.byte 64 # DW_AT_frame_base
.byte 24 # DW_FORM_exprloc
.byte 3 # DW_AT_name
.ascii "\202>" # DW_FORM_GNU_str_index
.byte 58 # DW_AT_decl_file
.byte 11 # DW_FORM_data1
.byte 59 # DW_AT_decl_line
.byte 11 # DW_FORM_data1
.byte 63 # DW_AT_external
.byte 25 # DW_FORM_flag_present
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 0 # EOM(3)
.section .debug_addr,"",@progbits
.Laddr_table_base0:
.quad .Lfunc_begin0
.section .debug_gnu_pubnames,"",@progbits
.long .LpubNames_end0-.LpubNames_begin0 # Length of Public Names Info
.LpubNames_begin0:
.short 2 # DWARF Version
.long .Lcu_begin0 # Offset of Compilation Unit Info
.long 48 # Compilation Unit Length
.long 25 # DIE offset
.byte 48 # Attributes: FUNCTION, EXTERNAL
.asciz "hello" # External Name
.long 0 # End Mark
.LpubNames_end0:
.section .debug_gnu_pubtypes,"",@progbits
.long .LpubTypes_end0-.LpubTypes_begin0 # Length of Public Types Info
.LpubTypes_begin0:
.short 2 # DWARF Version
.long .Lcu_begin0 # Offset of Compilation Unit Info
.long 48 # Compilation Unit Length
.long 0 # End Mark
.LpubTypes_end0:
.ident "clang version 11.1.0 (https://github.com/llvm/llvm-project.git 173544ee3d09cdce8665f2097f677c31e1f1a9a1)"
.section ".note.GNU-stack","",@progbits
.addrsig
.addrsig_sym printf
.section .debug_line,"",@progbits
.Lline_table_start0:

0 comments on commit 53a483c

Please sign in to comment.