1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 12:12:47 +01:00

[MSP430] Enable some basic support for debug information

This commit technically permits LLVM to emit the debug information for ELF files for MSP430 architecture. Aside from this, it only defines the register numbers as defined by part 10.1 of MSP430 EABI specification (assuming the 1-byte subregisters share the register numbers with corresponding full-size registers).

This commit was basically tested by me with TI-provided GCC 8.3.1 toolchain by compiling an example program with `clang` (please note manual linking may be required due to upstream `clang` not yet handling the `-msim` option necessary to run binaries on the GDB-provided simulator) and then running it and single-stepping with `msp430-elf-gdb` like this:

```
$sysroot/bin/msp430-elf-gdb ./test -ex "target sim" -ex "load ./test"
(gdb) ... traditional GDB commands follow ...
```

While this implementation is most probably far from completeness and is considered experimental, it can already help with debugging MSP430 programs as well as finding issues in LLVM debug info support for MSP430 itself.

One of the use cases includes trying to find a point where UBSan check in a trap-on-error mode was triggered.

The expected debug information format is described in the [MSP430 Embedded Application Binary Interface](http://www.ti.com/lit/an/slaa534/slaa534.pdf) specification, part 10.

Differential Revision: https://reviews.llvm.org/D81488
This commit is contained in:
Anatoly Trosinenko 2020-06-22 13:14:02 +03:00 committed by Anton Korobeynikov
parent ec3dc954d2
commit b2e4c430fd
4 changed files with 163 additions and 0 deletions

View File

@ -127,6 +127,27 @@ static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) {
}
}
static bool supportsMSP430(uint64_t Type) {
switch (Type) {
case ELF::R_MSP430_32:
case ELF::R_MSP430_16_BYTE:
return true;
default:
return false;
}
}
static uint64_t resolveMSP430(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
case ELF::R_MSP430_32:
return (S + getELFAddend(R)) & 0xFFFFFFFF;
case ELF::R_MSP430_16_BYTE:
return (S + getELFAddend(R)) & 0xFFFF;
default:
llvm_unreachable("Invalid relocation type");
}
}
static bool supportsPPC64(uint64_t Type) {
switch (Type) {
case ELF::R_PPC64_ADDR32:
@ -614,6 +635,8 @@ getRelocationResolver(const ObjectFile &Obj) {
case Triple::mipsel:
case Triple::mips:
return {supportsMips32, resolveMips32};
case Triple::msp430:
return {supportsMSP430, resolveMSP430};
case Triple::sparc:
return {supportsSparc32, resolveSparc32};
case Triple::hexagon:

View File

@ -24,4 +24,6 @@ MSP430MCAsmInfo::MSP430MCAsmInfo(const Triple &TT,
AlignmentIsInBytes = false;
UsesELFSectionDirectiveForBSS = true;
SupportsDebugInformation = true;
}

View File

@ -15,6 +15,7 @@ class MSP430Reg<bits<4> num, string n, list<string> alt = []> : Register<n> {
let Namespace = "MSP430";
let HWEncoding{3-0} = num;
let AltNames = alt;
let DwarfNumbers = [num];
}
class MSP430RegWithSubregs<bits<4> num, string n, list<Register> subregs,
@ -24,6 +25,7 @@ class MSP430RegWithSubregs<bits<4> num, string n, list<Register> subregs,
let Namespace = "MSP430";
let HWEncoding{3-0} = num;
let AltNames = alt;
let DwarfNumbers = [num];
}
//===----------------------------------------------------------------------===//

View File

@ -0,0 +1,136 @@
; RUN: llc --filetype=obj -o %t < %s
; RUN: llvm-dwarfdump --debug-info %t | FileCheck %s
; RUN: llvm-dwarfdump --verify %t
; This file was based on output of
;
; clang -target msp430 -S -emit-llvm -gdwarf-3 -Os dwarf-basics.c
;
; for the following dwarf-basics.c
;
; struct X {
; void *a;
; };
;
; int f(long y, struct X *p)
; {
; return 42;
; }
;
; CHECK: file format elf32-msp430
; CHECK: .debug_info contents:
; CHECK: Compile Unit: length = 0x{{.*}}, format = DWARF32, version = 0x0003, abbr_offset = 0x0000, addr_size = 0x02 (next unit at 0x{{.*}})
; CHECK: DW_TAG_compile_unit
; CHECK: DW_AT_producer ("clang version 11.0.0 (git@...)")
; CHECK: DW_AT_language (DW_LANG_C99)
; CHECK: DW_AT_name ("dwarf-basics.c")
; CHECK: DW_AT_stmt_list (0x{{.*}})
; CHECK: DW_AT_comp_dir ("/tmp")
; CHECK: DW_AT_low_pc (0x{{.*}})
; CHECK: DW_AT_high_pc (0x{{.*}})
; CHECK: DW_TAG_subprogram
; CHECK: DW_AT_low_pc (0x{{.*}})
; CHECK: DW_AT_high_pc (0x{{.*}})
; CHECK: DW_AT_frame_base (DW_OP_reg1 SPB)
; CHECK: DW_AT_name ("f")
; CHECK: DW_AT_decl_file ("/tmp/dwarf-basics.c")
; CHECK: DW_AT_decl_line (5)
; CHECK: DW_AT_prototyped (0x01)
; CHECK: DW_AT_type (0x{{.*}} "int")
; CHECK: DW_AT_external (0x01)
; CHECK: DW_TAG_formal_parameter
; CHECK: DW_AT_location (0x{{.*}}:
; CHECK: [0x0000, 0x0004): DW_OP_reg12 R12B)
; CHECK: DW_AT_name ("y")
; CHECK: DW_AT_decl_file ("/tmp/dwarf-basics.c")
; CHECK: DW_AT_decl_line (5)
; CHECK: DW_AT_type (0x{{.*}} "long int")
; CHECK: DW_TAG_formal_parameter
; CHECK: DW_AT_location (DW_OP_reg14 R14B)
; CHECK: DW_AT_name ("p")
; CHECK: DW_AT_decl_file ("/tmp/dwarf-basics.c")
; CHECK: DW_AT_decl_line (5)
; CHECK: DW_AT_type (0x{{.*}} "X*")
; CHECK: NULL
; CHECK: DW_TAG_base_type
; CHECK: DW_AT_name ("int")
; CHECK: DW_AT_encoding (DW_ATE_signed)
; CHECK: DW_AT_byte_size (0x02)
; CHECK: DW_TAG_base_type
; CHECK: DW_AT_name ("long int")
; CHECK: DW_AT_encoding (DW_ATE_signed)
; CHECK: DW_AT_byte_size (0x04)
; CHECK: DW_TAG_pointer_type
; CHECK: DW_AT_type (0x{{.*}} "X")
; CHECK: DW_TAG_structure_type
; CHECK: DW_AT_name ("X")
; CHECK: DW_AT_byte_size (0x02)
; CHECK: DW_AT_decl_file ("/tmp/dwarf-basics.c")
; CHECK: DW_AT_decl_line (1)
; CHECK: DW_TAG_member
; CHECK: DW_AT_name ("a")
; CHECK: DW_AT_type (0x{{.*}} "*")
; CHECK: DW_AT_decl_file ("/tmp/dwarf-basics.c")
; CHECK: DW_AT_decl_line (2)
; CHECK: DW_AT_data_member_location (0x00)
; CHECK: NULL
; CHECK: DW_TAG_pointer_type
; CHECK: NULL
source_filename = "dwarf-basics.c"
target datalayout = "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16"
target triple = "msp430"
%struct.X = type { i8* }
define i16 @f(i32 %y, %struct.X* %p) !dbg !7 {
entry:
call void @llvm.dbg.value(metadata i32 %y, metadata !18, metadata !DIExpression()), !dbg !20
call void @llvm.dbg.value(metadata %struct.X* %p, metadata !19, metadata !DIExpression()), !dbg !20
ret i16 42, !dbg !21
}
declare void @llvm.dbg.value(metadata, metadata, metadata)
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4, !5}
!llvm.ident = !{!6}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 11.0.0 (git@...)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
!1 = !DIFile(filename: "dwarf-basics.c", directory: "/tmp")
!2 = !{}
!3 = !{i32 7, !"Dwarf Version", i32 3}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"wchar_size", i32 2}
!6 = !{!"clang version 11.0.0 (git@...)"}
!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 5, type: !8, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !17)
!8 = !DISubroutineType(types: !9)
!9 = !{!10, !11, !12}
!10 = !DIBasicType(name: "int", size: 16, encoding: DW_ATE_signed)
!11 = !DIBasicType(name: "long int", size: 32, encoding: DW_ATE_signed)
!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 16)
!13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X", file: !1, line: 1, size: 16, elements: !14)
!14 = !{!15}
!15 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !13, file: !1, line: 2, baseType: !16, size: 16)
!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 16)
!17 = !{!18, !19}
!18 = !DILocalVariable(name: "y", arg: 1, scope: !7, file: !1, line: 5, type: !11)
!19 = !DILocalVariable(name: "p", arg: 2, scope: !7, file: !1, line: 5, type: !12)
!20 = !DILocation(line: 0, scope: !7)
!21 = !DILocation(line: 7, column: 3, scope: !7)