Compatibility between IAR C/C++ Compiler and GCC - c

I have a code-block, which is written in C for IAR C/C++ Compiler.
__no_init uint8_t u8ramPhysStart_startUp # 0x20000000;
__no_init uint8_t u8ramPhysEnd_startUp # 0x2002FFFF;
__no_init uint8_t u8ramTestStart_startUp # 0x20004008;
__no_init uint8_t u8ramTestEnd_startUp # 0x20008008;
#define START_ASM (&u8ramPhysStart_startUp)
#define RAMSTART_STRTUP ((uint32_t)START_ASM)
My goal is converting it or rather making it GCC compatible. For this, I rewrite above code like:
unsigned char u8ramPhysStart_startUp __asm("# 0x20000000");
unsigned char u8ramPhysEnd_startUp __asm("# 0x2002FFFF");
unsigned char u8ramTestStart_startUp __asm("# 0x20004008");
unsigned char u8ramTestEnd_startUp __asm("# 0x20008008");
But after compilation I get following error:
C:\Users\Pc\AppData\Local\Temp\ccyuCWQT.s: Assembler messages:
C:\Users\Pc\AppData\Local\Temp\ccyuCWQT.s:971: Error: expected symbol name
C:\Users\Pc\AppData\Local\Temp\ccyuCWQT.s:972: Error: expected symbol name
Do someone knows, what it means?

I believe the gcc code should be something like
uint8_t __attribute__ ((section(".my_section"))) u8ramPhysStart_startUp;
where .my_section is something you have added to the linker script.
That being said, the only way which you can make allocation at absolute addresses portable, is to stick to pure ISO C:
#define u8ramPhysStart_startUp (*(volatile uint8_t*)0x20000000u)
or in case you want a pointer to an address:
#define u8ramPhysStart_startUp ((volatile uint8_t*)0x20000000u)
The disadvantage of this is that it doesn't actually allocate any memory, but relies on a linker script to handle that part. That's preferable in most cases.
Another disadvantage is that you won't be able to view these "variable" names in a debugger, since they are actually not variables at all. And that's the main reason why some tool chains come up with things like the non-standard # syntax.

Related

I would like to know why this code is used to specify address

#define NVRAM1_PAGE1_FIRST_ADDRESS 0x1000
extern volatile INT16U NVRAM_content[128] __attribute((nodp, addr(NVRAM1_PAGE1_FIRST_ADDRESS)));
This array surely start address from NVRAM1_PAGE1_FIRST_ADDRESS
but How does this code work?
I mean, I was trying to find 'nodp' meaning but there was no information in code or manual.

How to Compile a C program which contains 32bit asm into .o file?

Introduction
I'm following through the book "Learning Linux Binary Analysis". I have some experience working with 32 bit assembly and C (however still consider myself a novice). However I'm having trouble and confusion of how to compile a c program , which contains 32 bit assembly into an object file .o. So im guessing this is just a compilation issue on my part.
The Source code is for part of an example of code injection-based binary patching.
Source Code
#include <sys/syscall.h>
int _write (int fd, void *buf, int count)
{
long ret;
__asm__ __volatile__ ("pushl %%ebx\n\t"
"movl %%esi,%%ebx\n\t"
"int $0x80\n\t""popl %%ebx":"=a" (ret)
:"0" (SYS_write), "S" ((long) fd),
"c" ((long) buf), "d" ((long) count));
if (ret >= 0) {
return (int) ret;
}
return -1;
}
int evil_puts(void)
{
_write(1, "HAHA puts() has been hijacked!\n", 31);
}
The problem
I attempt to compile evil_puts.c into .o file. Which will then be used later for injection into another simple program.
gcc -c evil_puts.c
evil_puts.c: Assembler messages:
evil_puts.c:5: Error: invalid instruction suffix for `push'
evil_puts.c:8: Error: invalid instruction suffix for `pop'
I've received this before when working with 32 assembly with gas. And to solve this i put the '-32' flag when compiling and linking. Which i'm guessing is the problem? however not completely sure, and don't have an idea of how to compile it in 32 bit with C and gcc if that's the case?
I also attempted to change it to 64bit to see if it would work, by replacing 'l' of every command to 'q' and changing the registers to begin with 'r'. which seems to work. However the book uses 32 bit. So i wish to keep it that way. Any ideas? Sorry if this is a really basic question.
Also tried '-m32' but receive this:
fatal error: sys/syscall.h: No such file or directory
Use gcc -m32 -c evil_puts.c -o evil_puts.o
You're getting that error because you don't have the 32-bit libraries installed.
If using Ubuntu:
sudo apt-get install gcc-multilib
Knowledge specific to 32-bit x86 is of limited usefulness these days since basically everybody has switched to 64-bit (this is a good thing - 32-bit has a lot of register pressure and address space pressure).
Luckily, you don't actually need any asm for what you're doing. I've also made a couple sanity fixes:
#define _GNU_SOURCE
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#define write_str(fd, s) my_write(fd, s, strlen(s))
static ssize_t my_write(int fd, const void *buf, size_t count)
{
return syscall(SYS_write, (long)fd, (long)buf, (long)count);
}
int puts(const char *s __attribute__((unused)))
{
write_str(STDOUT_FILENO, "HAHA puts() has been hijacked!\n");
return strlen(s) + 1;
}
I'm not sure exactly why you're avoiding write(2). But if you really need to avoid syscall(2) as well, it will still be far easier to implement that single function in assembly than write assembly everywhere.

Declare a specific address for a string in MPLAB XC8 Microchip compiler

With compiler C18 when I want to use a specific address for a string I use:
In .C
#pragma romdata idsoft
const rom unsigned char _app_nfo[31]= {"V0.0 No - 05/12/12"};
#pragma romdata
in linker:
CODEPAGE NAME=idsoft START=0x78E0 END=0x78FE
How can i do same with XC8?
I've try many things, but none of them are working.
in XC8 linker parameter:
-L-pappnfo=0x78E0
In .C :
unsigned char __section ("appnfo") app_nfo[31];
It's not working.
You have just to do this:
unsigned char _app_nfo[31] # 0x78E0 = {"V0.0 No - 05/12/12"};
See 5.5.4.2 ABSOLUTE OBJECTS IN PROGRAM MEMORY in MPLAB XC8 C Compiler User’s Guide

Tiny C Compiler: "error: unknown opcode 'jmp'"

Given this code:
int main(void)
{
__asm volatile ("jmp %eax");
return 0;
}
32-bit TCC will complain with:
test.c:3: error: unknown opcode 'jmp'
but the 64-bit version will compile just fine.
What's the problem with the 32 bit code?
The solution is to simply add a star (*) before the register, like this:
__asm volatile ("jmp *%eax");
I'm not exactly sure what the star means. According to this SO post:
The star is some syntactical sugar indicating that control is to be passed indirectly, by reference/pointer.
As for why it works with 64-bit TCC, I assume that it's a bug; 64-bit GCC complains with Error: operand type mismatch for 'jmp', as it should.

use gcc compile a project that shows "undefined reference to `abort'"

I wrote a printf myselef that use va_list/va_arg/va_start/va_end/va_arg.
typedef char *va_list;
#define _AUPBND (sizeof (acpi_native_int) - 1)
#define _ADNBND (sizeof (acpi_native_int) - 1)
#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd)))
#define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
#define va_end(ap) (void) 0
#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))
At first,I copy these macros from linux kernel and the printf can print 32-bit integer correct but cannot print 64-bit integer and print double/float may fail or collapse.Then I check the code and I guess the va_* may have errors,so I use __builtin_va_* instead of kernel's va_*.
typedef __builtin_va_list va_list;
#define va_start(v,l) __builtin_va_start(v,l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)
But gcc prompt "undefined reference to `abort'",so I write a empty abort() and myprintf works corretly.
My questions are:
Why linux kernel's va_list/va_arg/va_start/va_end/va_arg can not used for printf 64-bit integer and double/float?
When I used __builtin_va_start/__builtin_va_arg/__builtin_va_end/__builtin_va_list, why gcc prompt "undefined reference to abort'"? But I can not find the definition of__builtin_va_*`, where're their definition?
Don't cut and paste things from the Linux headers. Instead, put this at the top of your source file:
#include <stdarg.h>
This will give you everything you need in order to use va_list and va_arg. However, it won't pull in printf or any of the standard I/O stuff (which lives in <stdio.h>).
gcc's __builtin_va_arg() apparently will call abort() (at least on some platforms or situations) if it's invoked with a type argument cannot have been passed in the ... part of the argument list for a function call.
For example, due to promotions a char or float passed as such an argument will have been promoted to int or double. Accessing those arguments as va_arg(ap,char) or va_arg(ap,float) is undefined behavior and gcc may call abort() in that situation - or it may do something else (my MinGW compiler will execute an invalid instruction to cause a crash).
You might see something like this when compiled:
In file included from D:\temp\test.c:2:0:
D:\temp\test.c: In function 'foo':
D:\temp\test.c:12:16: warning: 'char' is promoted to 'int' when passed through '...' [enabled by default]
c = va_arg(ap,char);
^
D:\temp\test.c:12:16: note: (so you should pass 'int' not 'char' to 'va_arg')
D:\temp\test.c:12:16: note: if this code is reached, the program will abort
The 'definition' of __builtin_va_* is compiled into the compiler (that's why 'builtin' is part of the name).
As far as the Linux macros for varargs access: while the definitions you took from a linux kernel header do exist in include/acpi/platform/acenv.h, if you look carefully at the conditional compilation in effect, you'll see that those macros aren't used when building the linux kernel. I'm not exactly sure when those macros are in effect, but they won't work with x64/x86-64/amd64 builds because the ABI on that platform isn't entirely stack-based. See section 3.5.6 of the "System V Application Binary Interface - AMD64 Architecture Processor Supplement" for details.

Resources