Add dwarf clang support

This if for clang (pre)release 15.0.0.

tccrun.c:
- update directory/filename read. clang has extra md5 section
- start with filename 0 instead of 1. clang starts at 0
- change dwarf_read_32/dwarf_read_64 into macros

x86_64-link.c:
- Add support for R_X86_64_DTPOFF64/R_X86_64_TPOFF64. Needed by clang

tests/tcctest.c:
- add prototypes for puts/alloca. clang fails with error
- disable other_constraints_test for clang. clang prints 1 instead of 0
This commit is contained in:
herman ten brugge 2022-05-07 18:10:59 +02:00
parent 18808e325f
commit 499cf2305b
3 changed files with 96 additions and 50 deletions

124
tccrun.c
View File

@ -634,33 +634,24 @@ dwarf_read_sleb128(unsigned char **ln, unsigned char *end)
return retval;
}
static unsigned int dwarf_read_32(unsigned char **ln, unsigned char *end)
{
unsigned char *cp = *ln;
unsigned int retval = 0;
if ((cp + 4) < end) {
retval = read32le(cp);
cp += 4;
}
*ln = cp;
return retval;
}
#if PTR_SIZE == 8
static unsigned long long dwarf_read_64(unsigned char **ln, unsigned char *end)
{
unsigned char *cp = *ln;
unsigned long long retval = 0;
if ((cp + 8) < end) {
retval = read64le(cp);
cp += 8;
}
*ln = cp;
return retval;
}
#endif
#define dwarf_read_1(ln,end) \
DW_GETC((ln), (end))
#define dwarf_read_2(ln,end) \
((ln) + 2 < (end) ? (ln) += 2, read16le((ln) - 2) : 0)
#define dwarf_read_4(ln,end) \
((ln) + 4 < (end) ? (ln) += 4, read32le((ln) - 4) : 0)
#define dwarf_read_8(ln,end) \
((ln) + 8 < (end) ? (ln) += 8, read64le((ln) - 8) : 0)
#define dwarf_ignore_type(ln, end) /* timestamp/size/md5/... */ \
switch (entry_format[j].form) { \
case DW_FORM_data1: (ln) += 1; break; \
case DW_FORM_data2: (ln) += 2; break; \
case DW_FORM_data4: (ln) += 3; break; \
case DW_FORM_data8: (ln) += 8; break; \
case DW_FORM_data16: (ln) += 16; break; \
case DW_FORM_udata: dwarf_read_uleb128(&(ln), (end)); break; \
default: goto next_line; \
}
static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc,
const char *msg, const char *skip)
@ -678,7 +669,13 @@ static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc,
unsigned int opindex;
unsigned int col;
unsigned int i;
unsigned int j;
unsigned int len;
unsigned int value;
struct {
unsigned int type;
unsigned int form;
} entry_format[256];
unsigned int dir_size;
#if 0
char *dirs[DIR_TABLE_SIZE];
@ -707,7 +704,7 @@ next:
line = 1;
filename = NULL;
function = NULL;
size = dwarf_read_32(&ln, rc->dwarf_line_end);
size = dwarf_read_4(ln, rc->dwarf_line_end);
end = ln + size;
version = DW_GETC(ln, end);
version += DW_GETC(ln, end) << 8;
@ -729,29 +726,58 @@ next:
ln += 12;
if (version >= 5) {
col = DW_GETC(ln, end);
for (i = 0; i < col * 2; i++)
dwarf_read_uleb128(&ln, end);
for (i = 0; i < col; i++) {
entry_format[i].type = dwarf_read_uleb128(&ln, end);
entry_format[i].form = dwarf_read_uleb128(&ln, end);
}
dir_size = dwarf_read_uleb128(&ln, end);
for (i = 0; i < dir_size; i++)
for (i = 0; i < dir_size; i++) {
for (j = 0; j < col; j++) {
if (entry_format[j].type == DW_LNCT_path) {
if (entry_format[j].form != DW_FORM_line_strp)
goto next_line;
#if 0
if (i < DIR_TABLE_SIZE)
dirs[i] = (char *)rc->dwarf_line_str + dwarf_read_32(&ln, end);
else
value = dwarf_read_4(ln, end);
if (i < DIR_TABLE_SIZE)
dirs[i] = (char *)rc->dwarf_line_str + value;
#else
dwarf_read_4(ln, end);
#endif
dwarf_read_32(&ln, end);
}
else
dwarf_ignore_type(ln, end);
}
}
col = DW_GETC(ln, end);
for (i = 0; i < col * 2; i++)
dwarf_read_uleb128(&ln, end);
for (i = 0; i < col; i++) {
entry_format[i].type = dwarf_read_uleb128(&ln, end);
entry_format[i].form = dwarf_read_uleb128(&ln, end);
}
filename_size = dwarf_read_uleb128(&ln, end);
for (i = 0; i < filename_size; i++)
if (i < FILE_TABLE_SIZE) {
filename_table[i].name = (char *)rc->dwarf_line_str + dwarf_read_32(&ln, end);
filename_table[i].dir_entry = dwarf_read_uleb128(&ln, end);
}
else {
dwarf_read_32(&ln, end);
dwarf_read_uleb128(&ln, end);
}
for (j = 0; j < col; j++) {
if (entry_format[j].type == DW_LNCT_path) {
if (entry_format[j].form != DW_FORM_line_strp)
goto next_line;
value = dwarf_read_4(ln, end);
if (i < FILE_TABLE_SIZE)
filename_table[i].name =
(char *)rc->dwarf_line_str + value;
}
else if (entry_format[j].type == DW_LNCT_directory_index) {
switch (entry_format[j].form) {
case DW_FORM_data1: value = dwarf_read_1(ln, end); break;
case DW_FORM_data2: value = dwarf_read_2(ln, end); break;
case DW_FORM_data4: value = dwarf_read_4(ln, end); break;
case DW_FORM_udata: value = dwarf_read_uleb128(&ln, end); break;
default: goto next_line;
}
if (i < FILE_TABLE_SIZE)
filename_table[i].dir_entry = value;
}
else
dwarf_ignore_type(ln, end);
}
}
else {
while ((DW_GETC(ln, end))) {
@ -776,8 +802,8 @@ next:
dwarf_read_uleb128(&ln, end); // size
}
}
if (filename_size >= 2)
filename = filename_table[1].name;
if (filename_size >= 1)
filename = filename_table[0].name;
while (ln < end) {
last_pc = pc;
switch (DW_GETC(ln, end)) {
@ -792,9 +818,9 @@ next:
goto next_line;
case DW_LNE_set_address:
#if PTR_SIZE == 4
pc = dwarf_read_32(&cp, end);
pc = dwarf_read_4(cp, end);
#else
pc = dwarf_read_64(&cp, end);
pc = dwarf_read_8(cp, end);
#endif
if (rc->num_callers < 0)
pc = rc->dwarf_text; /* dll */

View File

@ -78,6 +78,9 @@ typedef __SIZE_TYPE__ uintptr_t;
#include incname
#include stringify(funnyname)
int puts(const char *s);
void *alloca(size_t size);
int fib(int n);
void num(int n);
void forward_ref(void);
@ -3409,7 +3412,7 @@ void other_constraints_test(void)
{
unsigned long ret;
int var;
#ifndef _WIN64
#if !defined(_WIN64) && CC_NAME != CC_clang
__asm__ volatile ("mov %P1,%0" : "=r" (ret) : "p" (&var));
printf ("oc1: %d\n", ret == (unsigned long)&var);
#endif

View File

@ -48,6 +48,8 @@ int code_reloc (int reloc_type)
case R_X86_64_TLSLD:
case R_X86_64_DTPOFF32:
case R_X86_64_TPOFF32:
case R_X86_64_DTPOFF64:
case R_X86_64_TPOFF64:
return 0;
case R_X86_64_PC32:
@ -96,6 +98,8 @@ int gotplt_entry_type (int reloc_type)
case R_X86_64_TLSLD:
case R_X86_64_DTPOFF32:
case R_X86_64_TPOFF32:
case R_X86_64_DTPOFF64:
case R_X86_64_TPOFF64:
case R_X86_64_REX_GOTPCRELX:
case R_X86_64_PLT32:
case R_X86_64_PLTOFF64:
@ -365,6 +369,19 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
add32le(ptr, x);
}
break;
case R_X86_64_DTPOFF64:
case R_X86_64_TPOFF64:
{
ElfW(Sym) *sym;
Section *sec;
int32_t x;
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
sec = s1->sections[sym->st_shndx];
x = val - sec->sh_addr - sec->data_offset;
add64le(ptr, x);
}
break;
case R_X86_64_NONE:
break;
case R_X86_64_RELATIVE: