Le jeudi 24 janvier 2013 11:35:30, Thomas Preud'homme a écrit : > > I finally got around to look in this last failure. I just started but the > good news is that it's limited to the -run function. There is no problem > when compiling the example. Objdump shows it's the exact same code in both > case. So it's probably a relocation bug.
Ok got it. Fix attached. I'm not sure about the comments though, as I don't have all the details in my mind. Let me explain a bit what's going on and you might have idea about the details. The segfault happens when calling a function whose symbol is resolved by calling a function first (symbol is of type STT_GNU_IFUNC) and that you resolve the symbol later via a call to dlsym. In the case of the 28_strings test, tcc was calling strcpy and then while doing -run, it performed a dlsym for the first symbol it encountered in 28_strings.c: strcpy. The problem is that tcc, when linking, was copying the type for functions symbol (STT_FUNC and STT_GNU_IFUNC) in the resulting executable. I'm not sure about the details but what happens is that the first call to strcpy will save call the dynamic resolver which will call the function to decide which version of strcpy to use (like strcpy_sse2 or strcpy__ssse3) and then the resulting address was stored somewhere (I always forget the details about where is the results stored, is it just in the GOT of the executable?). Then, the dlsym would take the address stored and do the relocation again. Except that this time the adress points to one of the implementation of strcpy (strcpy_ssse3 on my computer) which would get executed to get the final address. So strcpy would be executed with whatever happens to be in the registers at the time of calling dlsym. Setting the symbol as STT_FUNC in the executable would mean that the dlsym would get the address of the resolving function which would return the address of the right variant of strcpy. So, all I can say is that using STT_FUNC instead of STT_GNU_IFUNC in the *executable* only affects the normal call, which would store the address of the resolving strcpy function instead of the strcpy variant directly. If someone can throw some light to where are things stored or suggest me a comment, I'd be very happy. Best regards, Thomas
diff --git a/tccelf.c b/tccelf.c
index da81d03..76a8002 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -1633,7 +1633,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
type = ELFW(ST_TYPE)(esym->st_info);
if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
put_got_entry(s1, R_JMP_SLOT, esym->st_size,
- ELFW(ST_INFO)(STB_GLOBAL,type),
+ ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
sym - (ElfW(Sym) *)symtab_section->data);
} else if (type == STT_OBJECT) {
unsigned long offset;
signature.asc
Description: This is a digitally signed message part.
_______________________________________________ Tinycc-devel mailing list [email protected] https://lists.nongnu.org/mailman/listinfo/tinycc-devel
