Closed 8785benjamin closed 6 years ago
@8785benjamin Could you add a pull request for your code changes?
Yes, I have tried to done it. I have created a fork containing all the modifications in case you want to have a look https://github.com/8785benjamin/binutils-esp32ulp
Hi Benjamin, I have include your function into the binutils-esp32ulp source code. New release will be soon. Great work! Thank you very much.
Thank you
Hi I have discovered that esp32ulp-elf-as does not generate correct relocation information in the .o file in some particular cases. Eg:
.macro test label: wait 1 jump label .endm .text test
In such a situation, as will indicate that the relocation to be applied to jump label has to be applied on the first instruction (ie. wait 1). This is what esp32ulp-elf-readelf confirms:Offset is 0 instead of 4 (bytes) so esp32ulp-elf-ld will apply the relocation to wait and not to jump and will corrupt the code. The same kind of issue will always happen in macro if the relocation is not the first instruction of the macro. Same will apply if we gather several instructions on the same line (a macro is handled this way):
loop: wait 1; jump loop;
After many hours of investigation I have found that the problem is located in tc-esp32ulp.c in the function md_assemble(). It always applies the relocation to the offset 0 of the current fragment of code (a fragment of code is a set of instructions ; in this implementation a fragment of code is all the instructions that appear on the same line, meaning that a new fragment is generated on every new line). Of course this does not work with macro's neither since when we handle the instructions inside of the macro, we stay on the same line of the source code. Faulty code:
Moreover there is another bug (which does not cause problem in practice) : the loop will dump to the instruction buffer all what is coming out of the parser, whereas we shall only put the 4 bytes of the instruction. In theory it causes a buffer overflow but by chance will not corrupt anything.
I propose the following implementation of the md_assemble:
I'm passing toP - frag_now->fr_literal as the offset to fix_new(). This is done in a similar way in several other architecture implementation. It is of course important to NOT increment toP during the while(), ie. we need to correct the second bug. We could also use directly frag_now_fix() to get the offset of the instruction in the code fragment, w/o forgetting to substract 4 bytes since it has been incremented by the call to frag_more() a few lines above...
Also, please correct the issue on line 2705 of binutils/stabs.c: if (*pp == ';' || pp == '\0') to be changed to if (pp == ';' || pp == '\0')
The compilers outputs a big warning (!). Issue has been correctly several versions ago in the original binutils. You may also consider removing all the other processor architecture and keep only esp32ulp, that would make the exe smaller.