This is the function in u-boot's bootm.c from where the kernel is launched:
/* Subcommand: GO */
static void boot_jump_linux(bootm_headers_t *images, int flag)
{
#ifdef CONFIG_ARM64
void (*kernel_entry)(void *fdt_addr);
int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
kernel_entry = (void (*)(void *fdt_addr))images->ep;
debug("## Transferring control to Linux (at address %lx)...\n",
(ulong) kernel_entry);
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
announce_and_cleanup(fake);
if (!fake)
kernel_entry(images->ft_addr);
#else
unsigned long machid = gd->bd->bi_arch_number;
char *s;
void (*kernel_entry)(int zero, int arch, uint params);
unsigned long r2;
int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
kernel_entry = (void (*)(int, int, uint))images->ep;
s = getenv("machid");
if (s) {
strict_strtoul(s, 16, &machid);
printf("Using machid 0x%lx from environment\n", machid);
}
debug("## Transferring control to Linux (at address %08lx)" \
"...\n", (ulong) kernel_entry);
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
announce_and_cleanup(fake);
if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
r2 = (unsigned long)images->ft_addr;
else
r2 = gd->bd->bi_boot_params;
if (!fake)
kernel_entry(0, machid, r2);
#endif
}
I am facing difficulty in understanding how kernel_entry is working here. Especially in the second-last line it is being used as:
kernel_entry(0, machid, r2);
So where is the definition of kernel_entry()? I failed to find in entire u-boot and kernel source code.
Update
I am rephrasing my question here:
Suppose kernel_entry is a pointer to a function and is being defined as:
bootm_headers_t *images
kernel_entry = (void (*)(int, int, uint))images->ep;
Then somewhere in the program it is being called as:
kernel_entry(0, machid, r2);
I understand being a pointer, kernel_entry should store an address of a function. But I want to understand what operations will be performed on the three arguments. Why do we have those arguments?
The declaration of kernel_entry variable and its type, which is a pointer to a function taking int, int, uint and returning void (probably the most confusing part), is here:
void (*kernel_entry)(int zero, int arch, uint params);
Assignment, images->ep is cast into desired signature function pointer and put into the variable:
kernel_entry = (void (*)(int, int, uint))images->ep;
Finally, the function is called:
kernel_entry(0, machid, r2);
Please note that if CONFIG_ARM64 is defined, then the function kernel_entry points to has different signature:
void (*kernel_entry)(void *fdt_addr); //takes one void* param and returns void
U-Boot has the kernel image in its addressable memory space, reads an address contained in that image (at images->ep), and branches to that entry point address.
The "definition of kernel_entry()" is actually in kernel source code, the label "start" at arch/arm/boot/compressed/head.S is what you are looking for.
To understand the kernel boot process, IMO the definitive tutorial is chapter 5 of Hallinan "Embedded Linux Primer".
Related
I created a small unit test library in C.
Its main feature is the fact that you don't need to register your test functions, they are identified as test functions because they have a predefined prefix (test_).
For example, if you want to create a test function, you can write something like this:
int test_abc(void *t)
{
...
}
Yes, just like in Go.
To find the test functions, the runner:
takes the name of the executable from argv[0];
parses the ELF sections to find the symbol table;
from the symbol table, takes all the functions named test_*;
treats the addresses from the symbol table as function pointers;
invoke the test functions.
For PIE binaries, there is one additional step. To find the load address for the test functions, I assume there is a common offset that applies to all functions. To figure out the offset, I subtract the address of main (runtime, function pointer) from the address of main read from the symbol table.
All the things described above are working fine: https://github.com/rodrigo-dc/testprefix
However, as far as I understood, function pointer arithmetic is not allowed by the C99 standard.
Given that I have the address from the symbol table - Is there a reliable way to get the runtime address of functions (in case of PIE binaries)?
I was hoping for some linker variable, some base address, or anything like that.
Is there a reliable way to get the runtime address of functions (in case of PIE binaries)?
Yes: see this answer, and also the comment about using dladdr().
P.S. Note that taking address of main in C++ is not allowed.
Because you have an ELF executable, this probably precludes "funny" architectures (e.g. Intel 8051, PIC, etc.) that might have segmented or non-linear, non-contiguous address spaces.
So, you [probably] can use the method you've described with main to get the actual address. You just need to convert to/from either char * or uintptr_t types so you are using byte offsets/differences.
But, you can also create a unified table of pointers to the various functions using by creating descriptor structs that are placed in a special linker section of your choosing using (e.g.) __attribute__((section("mysection"))
Here is some code that shows what I mean:
#include <stdio.h>
typedef struct {
int (*test_func)(void *); // pointer to test function
const char *test_name; // name of the test
int test_retval; // test return value
// more data ...
int test_xtra;
} testctl_t;
// define a struct instance for a given test
#define ATTACH_TEST(_func) \
testctl_t _func##_ctl __attribute__((section("testctl"))) = { \
.test_func = _func, \
.test_name = #_func \
}
// advance to next struct (must be 16 byte aligned)
#define TESTNEXT(_test) \
(testctl_t *) (((char *) _test) + asiz)
int
test_abc(void *t)
{
printf("test_abc: hello\n");
return 1;
}
ATTACH_TEST(test_abc);
int
test_def(void *t)
{
printf("test_def: hello\n");
return 2;
}
ATTACH_TEST(test_def);
int
main(void)
{
// these are special symbols defined by the linker for our special linker
// section that denote the start/end of the section (similar to
// _etext/_edata)
extern testctl_t __start_testctl;
extern testctl_t __stop_testctl;
size_t rsiz = sizeof(testctl_t);
size_t asiz;
testctl_t *test;
// align the size to a 16 byte boundary
asiz = rsiz;
asiz += 15;
asiz /= 16;
asiz *= 16;
// show the struct sizes
printf("main: sizeof(testctl_t)=%zx/%zx\n",rsiz,asiz);
// section start and stop symbol addresses
printf("main: start=%p stop=%p\n",&__start_testctl,&__stop_testctl);
// cross check of expected pointer values
printf("main: test_abc=%p test_abc_ctl=%p\n",test_abc,&test_abc_ctl);
printf("main: test_def=%p test_def_ctl=%p\n",test_def,&test_def_ctl);
for (test = &__start_testctl; test < &__stop_testctl;
test = TESTNEXT(test)) {
printf("\n");
// show the address of our test descriptor struct and the pointer to
// the function
printf("main: test=%p test_func=%p\n",test,test->test_func);
printf("main: calling %s ...\n",test->test_name);
test->test_retval = test->test_func(test);
printf("main: return is %d\n",test->test_retval);
}
return 0;
}
Here is the program output:
main: sizeof(testctl_t)=18/20
main: start=0x404040 stop=0x404078
main: test_abc=0x401146 test_abc_ctl=0x404040
main: test_def=0x401163 test_def_ctl=0x404060
main: test=0x404040 test_func=0x401146
main: calling test_abc ...
test_abc: hello
main: return is 1
main: test=0x404060 test_func=0x401163
main: calling test_def ...
test_def: hello
main: return is 2
How can I print the address of the instruction I am executing? For example let's consider the following main:
int main( void )
{
//printf("......\n");
printf("...Main...\n");
uint32_t nb,delay;
uint16_t result;
DD_SPI_STATUS status;
//Get SPI driver instance
DD_DRIVER_SPI* SPIdrv = DD_SPI_GetDriver(0);
printf("...DD_DRIVER_SPI* SPIdrv = DD_SPI_GetDriver(0)...\n");
DD_IRQ_Init();
printf("...DD_IRQ_Init()...\n");
// Initialize buffers
for (nb = 0; nb < sizeof(TxBuffer); nb++)
{
TxBuffer[nb] = nb & 0xFF;
}
// Initialize the SPI driver
SPIdrv->Initialize(SPI_callback);
printf("...SPIdrv->Initialize(SPI_callback)...\n");
// force driver reset
SPIdrv->Control( DD_SPI_MODE_INACTIVE, 0);
printf("...SPIdrv->Control( DD_SPI_MODE_INACTIVE, 0)...\n");
return 0;
}
How do I print the address of the instruction SPIdrv-> Control (DD_SPI_MODE_INACTIVE, 0); in such a way that by going to see the disassembled code I can immediately identify where I am?
you can print an address using %p formatting:
printf("SPIdrv->Initialize=%p\n", (void*)SPIdrv->Initialize);
There's no standard way to print the contents of the function as instructions. But if you google "C disassembler library" you'll find some functions you can download.
If you're trying to print the address in main() where you're calling the function, I don't think that's possible at all in standard C. GCC has an extension that allows you to get the address of a label, so you could do:
here:
SPIdrv->Initialize(SPI_callback);
printf("Called SPIdrv->Initialize at %p\n", &&here);
It's non-standard, but if you're using gcc there's an extension to get the address of a label, so if you had:
debug_point:
SPIdrv->Control( DD_SPI_MODE_INACTIVE, 0);
then &&debug_point would be a void * to that location in the code.
I have to change the designated section of function_b so that it changes the stack in such a way that the program prints:
Executing function_a
Executing function_b
Finished!
At this point it also prints Executed function_b in between Executing function_b and Finished!.
I have the following code and I have to fill something in, in the part where it says // ... insert code here
#include <stdio.h>
void function_b(void){
char buffer[4];
// ... insert code here
fprintf(stdout, "Executing function_b\n");
}
void function_a(void) {
int beacon = 0x0b1c2d3;
fprintf(stdout, "Executing function_a\n");
function_b();
fprintf(stdout, "Executed function_b\n");
}
int main(void) {
function_a();
fprintf(stdout, "Finished!\n");
return 0;
}
I am using Ubuntu Linux with the gcc compiler. I compile the program with the following options: -g -fno-stack-protector -fno-omit-frame-pointer. I am using an intel processor.
Here is a solution, not exactly stable across environments, but works for me on x86_64 processor on Windows/MinGW64.
It may not work for you out of the box, but still, you might want to use a similar approach.
void function_b(void) {
char buffer[4];
buffer[0] = 0xa1; // part 1
buffer[1] = 0xb2;
buffer[2] = 0xc3;
buffer[3] = 0x04;
register int * rsp asm ("rsp"); // part 2
register size_t r10 asm ("r10");
r10 = 0;
while (*rsp != 0x04c3b2a1) {rsp++; r10++;} // part 3
while (*rsp != 0x00b1c2d3) rsp++; // part 4
rsp -= r10; // part 5
rsp = (int *) ((size_t) rsp & ~0xF); // part 6
fprintf(stdout, "Executing function_b\n");
}
The trick is that each of function_a and function_b have only one local variable, and we can find the address of that variable just by searching around in the memory.
First, we put a signature in the buffer, let it be the 4-byte integer 0x04c3b2a1 (remember that x86_64 is little-endian).
After that, we declare two variables to represent the registers: rsp is the stack pointer, and r10 is just some unused register.
This allows to not use asm statements later in the code, while still being able to use the registers directly.
It is important that the variables don't actually take stack memory, they are references to processor registers themselves.
After that, we move the stack pointer in 4-byte increments (since the size of int is 4 bytes) until we get to the buffer. We have to remember the offset from the stack pointer to the first variable here, and we use r10 to store it.
Next, we want to know how far in the stack are the instances of function_b and function_a. A good approximation is how far are buffer and beacon, so we now search for beacon.
After that, we have to push back from beacon, the first variable of function_a, to the start of instance of the whole function_a on the stack.
That we do by subtracting the value stored in r10.
Finally, here comes a werider bit.
At least on my configuration, the stack happens to be 16-byte aligned, and while the buffer array is aligned to the left of a 16-byte block, the beacon variable is aligned to the right of such block.
Or is it something with a similar effect and different explanation?..
Anyway, so we just clear the last four bits of the stack pointer to make it 16-byte aligned again.
The 32-bit GCC doesn't align anything for me, so you might want to skip or alter this line.
When working on a solution, I found the following macro useful:
#ifdef DEBUG
#define show_sp() \
do { \
register void * rsp asm ("rsp"); \
fprintf(stdout, "stack pointer is %016X\n", rsp); \
} while (0);
#else
#define show_sp() do{}while(0);
#endif
After this, when you insert a show_sp(); in your code and compile with -DDEBUG, it prints what is the value of stack pointer at the respective moment.
When compiling without -DDEBUG, the macro just compiles to an empty statement.
Of course, other variables and registers can be printed in a similar way.
ok, let assume that epilogue (i.e code at } line) of function_a and for function_b is the same
despite functions A and B not symmetric, we can assume this because it have the same signature (no parameters, no return value), same calling conventions and same size of local variables (4 byte - int beacon = 0x0b1c2d3 vs char buffer[4];) and with optimization - both must be dropped because unused. but we must not use additional local variables in function_b for not break this assumption. most problematic point here - what is function_A or function_B will be use nonvolatile registers (and as result save it in prologue and restore in epilogue) - but however look like here no place for this.
so my next code based on this assumption - epilogueA == epilogueB (really solution of #Gassa also based on it.
also need very clearly state that function_a and function_b must not be inline. this is very important - without this any solution impossible. so I let yourself add noinline attribute to function_a and function_b. note - not code change but attribute add, which author of this task implicitly implies but not clearly stated. don't know how in GCC mark function as noinline but in CL __declspec(noinline) for this used.
next code I write for CL compiler where exist next intrinsic function
void * _AddressOfReturnAddress();
but I think that GCC also must have the analog of this function. also I use
void* _ReturnAddress();
but however really _ReturnAddress() == *(void**)_AddressOfReturnAddress() and we can use _AddressOfReturnAddress() only. simply using _ReturnAddress() make source (but not binary - it equal) code smaller and more readable.
and next code is work for both x86 and x64. and this code work (tested) with any optimization.
despite I use 2 global variables - code is thread safe - really we can call main from multiple threads in concurrent, call it multiple time - but all will be worked correct (only of course how I say at begin if epilogueA == epilogueB)
hope comments in code enough self explained
__declspec(noinline) void function_b(void){
char buffer[4];
buffer[0] = 0;
static void *IPa, *IPb;
// save the IPa address
_InterlockedCompareExchangePointer(&IPa, _ReturnAddress(), 0);
if (_ReturnAddress() == IPa)
{
// we called from function_a
function_b();
// <-- IPb
if (_ReturnAddress() == IPa)
{
// we called from function_a, change return address for return to IPb instead IPa
*(void**)_AddressOfReturnAddress() = IPb;
return;
}
// we at stack of function_a here.
// we must be really at point IPa
// and execute fprintf(stdout, "Executed function_b\n"); + '}' (epilogueA)
// but we will execute fprintf(stdout, "Executing function_b\n"); + '}' (epilogueB)
// assume that epilogueA == epilogueB
}
else
{
// we called from function_b
IPb = _ReturnAddress();
return;
}
fprintf(stdout, "Executing function_b\n");
// epilogueB
}
__declspec(noinline) void function_a(void) {
int beacon = 0x0b1c2d3;
fprintf(stdout, "Executing function_a\n");
function_b();
// <-- IPa
fprintf(stdout, "Executed function_b\n");
// epilogueA
}
int main(void) {
function_a();
fprintf(stdout, "Finished!\n");
return 0;
}
This is the function from u-boot:
static void boot_jump_linux(bootm_headers_t *images, int flag)
{
#ifdef CONFIG_ARM64
void (*kernel_entry)(void *fdt_addr);
int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
kernel_entry = (void (*)(void *fdt_addr))images->ep;
debug("## Transferring control to Linux (at address %lx)...\n",
(ulong) kernel_entry);
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
announce_and_cleanup(fake);
if (!fake)
kernel_entry(images->ft_addr);
#else
unsigned long machid = gd->bd->bi_arch_number;
char *s;
void (*kernel_entry)(int zero, int arch, uint params);
unsigned long r2;
int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
kernel_entry = (void (*)(int, int, uint))images->ep;
s = getenv("machid");
if (s) {
strict_strtoul(s, 16, &machid);
printf("Using machid 0x%lx from environment\n", machid);
}
debug("## Transferring control to Linux (at address %08lx)" \
"...\n", (ulong) kernel_entry);
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
announce_and_cleanup(fake);
if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
r2 = (unsigned long)images->ft_addr;
else
r2 = gd->bd->bi_boot_params;
if (!fake)
kernel_entry(0, machid, r2);
#endif
}
I understood from the related question: Trying to understand the usage of function pointer that kernel_entryis a pointer to a function. Can someone help me understand where that function is defined? I don't even know the name of this function so I failed to grepit.
NOTE: The entire u-boot source code is here.
Indeed kernel_entry is a function pointer. It is initialized from the ep field of the piece of data passed in called images, of type bootm_header_t. The definition of that struct is in include/image.h. This is the definition of a bootable image header, ie the header of a kernel image which contain the basic info to boot that image from the boot loader. Obviously, to start it, you need a program entry point, similarly to the main function in regular C programs.
In that structure, the entry point is simply defined as a memory address (unsigned long), which the code you listed cast into that function pointer.
That structure as been obtained from loading the first blocks of the image file on disk, whose location is known already by the boot loader.
Hence the actual code pointed by that function pointer belongs to a different binary, and the definition of the function must be located in a different source code. For a linux kernel, this entry point is an assembly hand coded function, whose source is in head.S. This function being highly arch dependent, you will find many files of that name implementing it accross the kernel tree.
The code below is just not working.
Can anybody point out why
#define STACK_SIZE 1524
static void mt_allocate_stack(struct thread_struct *mythrd)
{
unsigned int sp = 0;
void *stck;
stck = (void *)malloc(STACK_SIZE);
sp = (unsigned int)&((stck));
sp = sp + STACK_SIZE;
while((sp % 8) != 0)
sp--;
#ifdef linux
(mythrd->saved_state[0]).__jmpbuf[JB_BP] = (int)sp;
(mythrd->saved_state[0]).__jmpbuf[JB_SP] = (int)sp-500;
#endif
}
void mt_sched()
{
fprintf(stdout,"\n Inside the mt_sched");
fflush(stdout);
if ( current_thread->state == NEW )
{
if ( setjmp(current_thread->saved_state) == 0 )
{
mt_allocate_stack(current_thread);
fprintf(stdout,"\n Jumping to thread = %u",current_thread->thread_id);
fflush(stdout);
longjmp(current_thread->saved_state, 2);
}
else
{
new_fns();
}
}
}
All I am trying to do is to run the new_fns() on a new stack. But is is showing segmentation fault at new_fns().
Can anybody point me out what's wrong.
Apart all other considerations, you are using "&stck" instead ok "stck" as stack! &stck points to the cell containing the POINTER TO the allocated stack
Then, some observations:
1) setjmp is not intended for this purpose: this code may work only on some systems, and perhaps only with som runtime library versions.
2) I think that BP should be evaluated in some other way. I suggest to check how you compiled composes a stack frame. I.e., on x86 platforms EBP points to the base of the local context, and at *EBP you can find the address of the base of the calling context. ESP points to EBP-SIZE_OF_LOCAL_CONTEXT, different compilers usually compute that size in a different way.
As far as I can see, you are implementig some sort of "fibers". If you are working on Win32, there is aready a set of function that implements in a safe way this functionality (see "fibers"). On linux I suggest you to have a look to "libfiber".
Regards