avr-gdb can not understand my input address - avr

I use simavr and avr-gdb to debug a .hex file, here is the problem:
(gdb) i r pc
pc 0xcd0 0xcd0
(gdb) x/10i 0xc4
0x8000c4: nop
0x8000c6: nop
0x8000c8: nop
0x8000ca: nop
0x8000cc: nop
0x8000ce: nop
0x8000d0: nop
0x8000d2: nop
0x8000d4: nop
0x8000d6: nop
(gdb) x/10i $pc-0xc0c
0xc4: eor r1, r1
0xc6: out 0x3f, r1 ; 63
0xc8: ldi r28, 0xFF ; 255
0xca: ldi r29, 0x08 ; 8
0xcc: out 0x3e, r29 ; 62
0xce: out 0x3d, r28 ; 61
0xd0: ldi r17, 0x05 ; 5
0xd2: ldi r26, 0x00 ; 0
0xd4: ldi r27, 0x01 ; 1
0xd6: ldi r30, 0xEA ; 234
(gdb)
seems that avr-gdb can not understand my input address, and add an offset.

I'm the author of simavr. Sorry I'm not a member of stackoverflow.
The reason you see these addresses is that gdb/gcc do not handle very well architectures that have overlapping 'address space'. The AVR SRAM starts at 0x000, the AVR Flash starts also at 0x000 and the.... eeprom is ALSO considered to be at 0x000 -- this is the 'harvard' architecture.
So, to make gcc/gdb works, everything is compiled in 'virtual address spaces' by adding an arbitrary constant to these offsets -- So the breakdown is that the Flash is considered to be at 0x000 (fine!) the SRAM is considered to be at 0x800000 and the eeprom at 0x810000.
This allows gcc/gdb to be happy -- however the price to pay is that you will see these wierd addressed when debugging, as gdb firmly believe everything is at these offsets.
The best way to handle this is to ... ignore it! There's very little we can do -- I didn't come up with it, it was rolled into avr-gcc long before simavr started in 2009.
You can see the 'address decoder' for simavr addresses there, perhaps it makes things a little bit clearer.
https://github.com/buserror/simavr/blob/4c9efe1fc44b427a4ce1ca8e56e0843c39d0014d/simavr/sim/sim_gdb.c#L357
Hope this help -- if you have further questions, feel free to pop in to freenode #simavr, or even open and 'issue' on github.

Related

Call function in dynamic library in assembly?

I'm probably way off but this is what I did, I'm also trying to get this to work from linux to cross compile to mac
I did a hello world kind of thing in C with write, malloc and realloc. I notice in the assembly it used adrp but I couldn't figure out how to use that instruction. I kept getting a label must be GOT relative error. I was hoping I could use the section as the label but ended up writing a label which didn't help.
Essentially the write c stub function uses adrp, then ldr [x16, #24]. Since I couldn't figure out adrp I used mov and movk. It seemed to do the same thing but I got a segment fault when I execute it. Stepping through lldb it appears that the code did what I thought however the GOT section wasn't replaced at runtime like I thought it would. Objdump leaves me to believe I named the section right. I don't know if figuring out adrp is all I need to get this to work or if I did everything completely wrong
.global _main
.align 2
_main:
mov X0, #1
adr X1, hello
mov X2, #13
mov X16, #4
svc 0
mov x16, 16384
movk x16, 0x1, lsl 32
ldr x16, [x16, #24]
#adrp x16, HowGOTLabel
#ldr x16, [x16, #24]
br x16
mov X0, #0
mov X16, #1
svc 0
hello: .ascii "Hello\n"
.section __DATA_CONST,__got
.align 3
HowGOTLabel:
.word 0
.word 0x80100000
.word 1
.word 0x80100000
.word 2
.word 0x80100000
.word 3
.word 0x80000000
Darwin on arm64 forces all userland binaries to use ASLR, so you cannot use movz/movk for PC-relative addresses.
The reason why your adrp doesn't work is because it can only refer to 0x1000-byte aligned locations. For more granular targeting you'd use adr, but there you have the issue of being limited to ±1MB of the instruction. For Linux targets, the compiler seems to be more lenient here, but for Darwin targets, adr can only really be used for locations within the same section, and you're trying to refer to __DATA_CONST.__got from __TEXT.__text.
So how can you fix this? You use #PAGE and #PAGEOFF:
adrp x16, HowGOTLabel#PAGE
add x16, x16, HowGOTLabel#PAGEOFF
You can even have this be fixed up to adr+nop at link-time if the target is in range, with some asm directives:
Lloh0:
adrp x16, HowGOTLabel#PAGE
Lloh1:
add x16, x16, HowGOTLabel#PAGEOFF
.loh AdrpAdd Lloh0, Lloh1
You can also do this with AdrpLdr if the second instruction is ldr rather than add.
But once you fix that, you've got two other issues in your code:
You use br x16. This means you won't return to the callsite. Use blr for function calls.
You don't actually have any imports? It's not clear how you think this would end up calling library functions, but really you can just do it like this:
bl _printf
And the compiler and linker will take care of imports.

AVR gcrt1.S weird call

So basically i have decompiled unoptimized simple program and saw that it runs through gcrt1.S, and i dived in to assembly language and tried to understand what exactly it does. here is my code and my assumption of what it does
00000034 CLR R1 Clear Register
00000035 OUT 0x3F,R1 Out to I/O location
00000036 SER R28 Set Register
00000037 LDI R29,0x08 Load immediate
00000038 OUT 0x3E,R29 Out to I/O location
00000039 OUT 0x3D,R28 Out to I/O location
0000003A CALL 0x00000040 Call subroutine
0000003C JMP 0x00000050 Jump
0000003E JMP 0x00000000 Jump
Clear R1
Clear stratus register
Set R28 1111 1111
Here is where my questions start:
Load R29 from 0x08 (PORTC ?)
OUT to SPH <-R29
OUT to SPL <-R28
Call Main
The confuision that i have is why it loads byte from PORTC register, since the default would be 0x00 anyway
Microcontroller is atmega328p link to a datasheet
Load R29 from 0x08 (PORTC ?)
The instruction is LDI R29,0x08 which loads 8 into R29. LDI is "load immediate to register"; it does not read from memory, see section "31. Instruction Set Summary" in the ATmega328 manual you are using. The code is initializing the frame pointer Y from symbol __stack, see startup code in gcrt1.S.

LDMIA instruction not working correctly on external SRAM in cortex M4

I am using STM32L486ZG board in thumb mode. I am running a simple bare-metal application without any RTOS. I have external SRAM connected to the board using FSM. The external SRAM is located at address 0x60000000. The system is initialized and running at 72MHz (i have tried this issue with frequency from 18-80 MHz) now in my main function i have following code:
int main(){
asm volatile (
"push {r0}\n"
"mov r0, #0x60000000\n"
"add r0, #0x400\n"
"stmdb r0!, {r1-r12}\n"
"ldmia r0!, {r1-r12}\n"
"pop {r0}\n"
);
}
According to this code no register should be changed after this main function has executed, but that's not the case after the following instruction
ldmia r0!, {r1-r12}
i.e. r9 is not correct after execution. stmdb instruction is working correctly but ldmia is not loading the data correctly. I have verified this by viewing the contents from memory.
This issue is persistent with any arguments in the ldmia instruction: the 9th register is always affected.
Explanation:
Lets say I am debugging this code and the next instruction to execute is this:
stmdb r0!, {r1-r12}
after stepping up all these registers have been saved in the memory and value of r0 is 0x600003d0
the contents of memory:
0x600003D0 00000000 40021008 0000000C .......#....
0x600003DC 40000000 00000000 00000000 ...#........
0x600003E8 20017FEC 00000000 00000000 ì.. ........
0x600003F4 00000000 00000000 00000000 ............
content of the registers:
r0 0x600003d0
r1 0x00000000
r2 0x40021008
r3 0x0000000c
r4 0x40000000
r5 0x00000000
r6 0x00000000
r7 0x20017fec
r8 0x00000000
r9 0x00000000
r10 0x00000000
r11 0x00000000
r12 0x00000000
this shows that all the registers are successfully saved in the memory. Now i step the next instruction
ldmia r0!, {r1-r12}
after this
these are the contents of registers:
r0 0x60000400
r1 0x00000000
r2 0x40021008
r3 0x0000000c
r4 0x40000000
r5 0x00000000
r6 0x00000000
r7 0x20017fec
r8 0x00000000
r9 0x555555d5
r10 0x00000000
r11 0x00000000
r12 0x00000000
as you can see all the registers are restored except r9 which oddly has its value "pop"ed from 0x60000000 instead of 0x600003F0.
Any idea what could be causing this issue. I am using Jlink to write into flash.
P.S. This issue doesn't occur when the registers are saved to onchip SRAM as opposed to external SRAM;
edit
if the instruction
ldmia r0!, {r1-r12}
is split into two parts like:
ldmia r0!, {r1-r6}
ldmia r0!, {r7-r12}
then all the registers are restored successfully
You need to read the STM32L4xx6xx Silicon Limitations. Section 2.2.4 Read burst access of nine words or more is not supported by FMC. ( DocID026121 Rev 4 ) available from ST.
"CPU read burst access equal to or more than 9 registers to FMC returns corrupted data
starting from the 9th read word. These bursts can only be generated by Cortex®-M4 CPU
and not by the other masters (i.e not by DMA).
This issue occurs when the stack is remapped on the external memory on the FMC and
POP operations are performed with 9 or more registers.
This also occurs when LDM/VLDM operations are used with 9 or more registers."

Why call and ret functions work like this in assembly?

So, I was messing around with assembly, and stumbled upon weird thing. Before writing anything, I set registers to these values:
AX 0000, BX 0000, SP 00FD.
Lets say, that we write simple code, which increases registers AX and BX:
A100
INC AX
CALL 0200
A200
INC BX
RETN
After writing it, I tried to see how registers change when executing commands, one by one, using T command. First time, it increases AX, moves to 0200, increases BX and returns. Here is the weird bit: when it returns, it executes command:
ADD [BX+SI],AX and then calls 0200 again.
When it calls 0200 again, it repeats itself, but now, when it returns, it returns to CALL 0100 command (not to CALL 0200) and increases AX again and so on. Why is this happening?
I have image of full output, maybe this can help understand my question better?:
http://s18.postimg.org/wt6eracg9/Untitled.png
Based on your screenshots, your code seems to be this (filled with nop's, disassembled with udcli):
echo 40 e8 fc 00 01 00 e8 f7 00 e8 f4 ff x{1..244} 43 c3 | sed 's/x[0-9]*\>/90/g' | udcli -o 0x100 -x -16
0000000000000100 40 inc ax
0000000000000101 e8fc00 call word 0x200
0000000000000104 0100 add [bx+si], ax
0000000000000106 e8f700 call word 0x200
0000000000000109 e8f4ff call word 0x100
000000000000010c *** never reached ***
0000000000000200 43 inc bx
0000000000000201 c3 ret
The code flow is the following, line by line:
0000000000000100 40 inc ax
ax gets incremented.
0000000000000101 e8fc00 call word 0x200
Return address 0x104 gets pushed to the stack, ip (instruction pointer) is set to 0x200.
0000000000000200 43 inc bx
bx gets incremented.
0000000000000201 c3 ret
Near return, that is, ip is popped from stack. New ip will be 0x104.
0000000000000104 0100 add [bx+si], ax
The value of ax is added to the word value at [bx+si].
0000000000000106 e8f700 call word 0x200
Return address 0x109 gets pushed to the stack, ip (instruction pointer) is set to 0x200.
0000000000000200 43 inc bx
bx gets incremented.
0000000000000201 c3 ret
Near return, that is, ip is popped from stack. New ip will be 0x109.
0000000000000109 e8f4ff call word 0x100
Return address 0x10c gets pushed to the stack, ip (instruction pointer) is set to 0x100. So this is actually an infinite recursive function and will run out of stack.
So your problem is that you don't define the code after CALL 0200. There happens to be 01 00 (add [bx+si], ax) and after return it will be executed, and after it other undefined instructions.
My advice: download any decent assembler (NASM, YASM, FASM...) ASAP and don't ruin your life trying to write assembly code with DEBUG. Trying to write assembly programs with DEBUG is an attempt destined to fail.
On possible reason is that you don't have some exit, you didn't use DOS's 0x4c service, and the program get bound the code and started to execute random commands or the execution flow hit some ret instruction where no call is used, it then will behave unexpectedly.

x86 assember - illegal opcode 0xff /7 under Windows

I'm currently developing an x86 disassembler, and I started disassembling a win32 PE file. Most of the disassembled code looks good, however there are some occurences of the illegal 0xff /7 opcode (/7 means reg=111, 0xff is the opcode group inc/dec/call/callf/jmp/jmpf/push/illegal with operand r/m 16/32). The first guess was, that /7 is the pop instruction, but it is encoded with 0x8f /0. I've checked this against the official Intel Architecture Software Developer’s Manual Volume 2: Instruction Set Reference - so I'm not just missleaded.
Example disassembly: (S0000O0040683a is a lable being jumped to by another instruction)
S0000O0040683a: inc edi ; 0000:0040683a ff c7
test dword ptr [eax+0xff],edi ; 0000:0040683c 85 78 ff
0xff/7 edi ; 0000:0040683f ff ff
BTW: gdb disassembles this equally (except the bug 0xff not yielding -1 in my disassembly):
(gdb) disassemble 0x0040683a 0x00406840
Dump of assembler code from 0x40683a to 0x406840:
0x0040683a: inc %edi
0x0040683c: test %edi,0xffffffff(%eax)
0x0040683f: (bad)
End of assembler dump.
So the question is: Is there any default handler in the illegal opcode exception handler of Windows, which implements any functionality in this illegal opcode, and if yes: What happends there?
Regards, Bodo
After many many additional hours getting my disassembler to produce the output in the exact same syntax than gdb does, I could diff over the two versions. This revealed a rather awkward bug in my disassember: I forgot to take into account, that the 0x0f 0x8x jump instruction have a TWO byte opcode (plus the rel16/32 operand). So each 0x0f 0x8x jump target was off by one leading to code which is not reachable in reality. After fixing this bug, no 0xff/7 opcodes are disassembled any longer.
Thanks go to everyone answering to my question (and commenting that answers as well) and thus at least trying to help me.
Visual Studio disassembles this to the following:
00417000 FF C7 inc edi
00417002 85 78 FF test dword ptr [eax-1],edi
00417005 ?? db ffh
00417006 FF 00 inc dword ptr [eax]
Obviously, a general protection fault happens at 00417002 because eax does not point to anything meaningful, but even if I nop it out (90 90 90) it throws an illegal opcode exception at 00417005 (it does not get handled by the kernel). I'm pretty sure that this is some sort of data and not executable code.
To answer your question, Windows will close the application with the exception code 0xC000001D STATUS_ILLEGAL_INSTRUCTION. The dialog will match the dialog used for any other application crashes, whether it offers a debugger or to send an error report.
Regarding the provided code, it would appear to have either been assembled incorrectly (encoding a greater than 8-bit displacement) or is actually data (as suggested by others already).
It looks like 0xFFFFFFFF has been inserted instead of 0xFF for the test instruction, probably in error?
85 = test r/m32, and 78 is the byte for parameters [eax+disp8], edi, with the disp8 to follow which should just be 0xFF (-1) but as a 32-bit signed integer this is 0xFFFFFFFF.
So I am assuming that you have 85 78 FF FF FF FF where it should be 85 B8 FF FF FF FF for a 32-bit displacement or 85 78 FF for the 8-bit displacement? If this is the case the next byte in the code should be 0xFF...
Of course, as suggested already, this could just be data, and don't forget that data can be stored in PE files and there is no strong guarantee of any particular structure. You can actually insert code or user defined data into some of the MZ or PE header fields if you are agressively optimising to decrease the .exe size.
EDIT: as per the comments below I'd also recommend using an executable where you already know exactly what the expected disassembled code should be.

Resources