Could anyone please point me out what is the limitation to the alignment value which makes the creation of multiple segment for a section.
With The test case mentioned below:
#include <stdio.h>
#define SIZE (1 << 11)
int Buffer[SIZE] __attribute__ ((aligned (SIZE * sizeof(int)))) ;
int main (int argc, char * argv[])
{
printf("Test\n");
return 0;
}
And here if i change the macro as:
#define SIZE (1 << 11) to #define SIZE (1 << 12)
Without the above changes we see only two loadable segment while with the above changes we observed three loadable segment. As the alignment of BSS changes from 8K to 16K for GCC 4.8.1 which creates three loadable segments.
So can anyone please tell me what changes need to be done in linker script to make creation of only one loadable segment for data.
There are two ways of creating a linker script:
1. Under ld/emulparam directory there are shell script which creates linker script.
2. While other part of linker script came from the actual source.
Now in the source part there depends which linker you are using ie. GNU linker or gold linker.
GNU Linker script is build based on:
Under directory ~/binutils-2013.11/ld/emulparams/, there are different architecture specifics shell script based on different ELF type and platform like for i386/Vxworks
elf_i386_vxworks.sh
While still the rest of generic contains in the script came from the ld/elf sources.
While about segment creation then please look into procedure **bfd_boolean
_bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)**
under source "bfd/elf.c"
Related
Using arm-none-eabi-gcc compiler toolchain for arm microcontrollers, and am defining a specific section in FLASH where this foo variable should live.
Let's say I have the example definition:
int foo __attribute__((section(".bar"))) = 5;
What I have observed is that if .bar is not assigned in the linker script, than the build will successfully succeed and foo will live in RAM instead as initialized data (the constant initial value will of course add to the FLASH size as well). The annoying part is, the linker does not complain when the section does not exist and so if expecting data to reside in FLASH it may silently live in a non-fixed location in RAM. Is there a compile/linker option to force a failure if this occurs?
According to GNU ld documentation, ld can be told to handle orphan linker sections as errors using the --orphan-handling=error command-line option.
Assuming orphan.c does contain the following code:
int foo __attribute__((section(".bar"))) = 5;
int main(void)
{
return 0;
}
The following command does succeed:
aarch64-elf-gcc --specs=rdimon.specs -o orphan orphan.c
But that one does fail:
aarch64-elf-gcc --specs=rdimon.specs -Wl,--orphan-handling=error -o orphan orphan.c
c:/git/cortex-baremetal/opt/gcc-linaro-7.3.1-2018.05-i686-mingw32_aarch64-elf/bin/../lib/gcc/aarch64-elf/7.3.1/../../../../aarch64-elf/bin/ld.exe: error: unplaced orphan section `.tm_clone_table' from `c:/git/cortex-baremetal/opt/gcc-linaro-7.3.1-2018.05-i686-mingw32_aarch64-elf/bin/../lib/gcc/aarch64-elf/7.3.1/crtbegin.o'.
c:/git/cortex-baremetal/opt/gcc-linaro-7.3.1-2018.05-i686-mingw32_aarch64-elf/bin/../lib/gcc/aarch64-elf/7.3.1/../../../../aarch64-elf/bin/ld.exe: error: unplaced orphan section `.bar' from `C:\Users\user\AppData\Local\Temp\cc6aRct8.o'.
c:/git/cortex-baremetal/opt/gcc-linaro-7.3.1-2018.05-i686-mingw32_aarch64-elf/bin/../lib/gcc/aarch64-elf/7.3.1/../../../../aarch64-elf/bin/ld.exe: error: unplaced orphan section `.tm_clone_table' from `c:/git/cortex-baremetal/opt/gcc-linaro-7.3.1-2018.05-i686-mingw32_aarch64-elf/bin/../lib/gcc/aarch64-elf/7.3.1/crtend.o'.
It seems the default linker script I used for the purpose of this example is missing another section, '.tm_clone_table'. It would have to be fixed in order not to trigger an error when '.bar' section is properly defined.
(Apologies if it is simple, and I am simply being blind.)
main.cpp:
#include "a.h"
int main()
{
x = 4 ;
}
a.h:
extern int x ;
(For some reason this code worked during the first compilation, but not the second one.
Side question: Occasionally I have problems where I need to compile a code twice for it to work. Do I have compiler issues?)
As you know, building a C or C++ program involves three steps: preprocessing, compiling and linking. Here is a simple, non-technical description of what happens.
Preprocessing
The preprocessor will replace the #include "a.h" with the verbatim contents of the file a.h. This results in
extern int x;
int main()
{
x = 4;
}
Compiling
The compiler processes the output of the preprocessor. The extern int x; is a declaration only, not a definition. It tells the compiler that it can trust that somewhere else space is reserved for a variable called x of type int. (extern x means that x has so-called external linkage.) The compiler generates code to set this variable to 4, but marks the code to ask the linker to fill in the actual location of x once the linker has determined where it is defined.
Linking
The linker processes the object file generated by the compiler in the previous step. It looks for an actual definition of x but finds none (x was only declared but never defined) and issues an undefined symbol error.
If you want to see extern in action, simply create a third file, say b.cpp:
// b.cpp
int x;
If you now build a program consisting of main.cpp and b.cpp, the linker error disappears. b.cpp defines x, so the linker will pick up this definition and fill in the location of x in the placeholder code generated by the compilation of main.cpp where it gets set to 4.
As for the side question: I think your issue where compilation sometimes succeeds and sometimes not is likely due to some mistake on the operator's part :-)
For educational purposes, I want to implement a system call in Debian Wheezy. I wish to implement it on the kernel that comes in the linux-image-3.2.0--rt-amd64 package. Here is an overview of what I have tried:
To get the kernel source:
apt-get source linux-image-3.2.0-4-rt-amd64
From that, I get the following files/directories the directory I executed in:
linux_3.2.41.orig.tar.xz
linux_3.2.41-2+deb7u2.dsc
linux_3.2.41-2+deb7u2.debian.tar.xz
as well as:
linux_3.2.41
which contains the source code for the kernel.
Then, to make the necessary changes in order to add the system call, I basically followed this page:
How to write system calls on debian/ubuntu
The following is a condensed version of the instructions given there modified to reflect the changes I made.
+File 1: linux-x.x.x/vpart_syscalls/vpart_syscalls.c
#include <linux/linkage.h>
#include <linux/kernel.h>
asmlinkage long insert_partition(char*dest, const char* src)
{
printk("<--- the syscall has been called!");
return 0;
}
File 2: linux-x.x.x/vpart_syscalls/Makefile. Create a Makefile within the same test directory you created above and put this line in it:
obj-y := vpart_syscalls.o
File 3: linux-x.x.x/arch/x86/kernel/syscall_table_32.S. Now, you have to add your system call to the system call table. Append to the file the following line:
.long insert_partition
File 4: linux-x.x.x/arch/x86/include/asm/unistd_32.h
In this file, the names of all the system calls will be associated with a unique number. After the last system call-number pair, add a line
#define __NR_insert_partition 349
Then replace NR_syscalls value, stating total number of system calls with (the existing number incremented by 1) i.e. in this case the NR_syscalls should've been 338 and the new value is 339.
#define NR_syscalls 350
File 5: linux-x.x.x/include/linux/syscalls.h
Append to the file the prototype of our function.
asmlinkage long insert_partition(int lenTicks, int vpid);
just before the #endif line in the file.
File 6: Makefile at the root of source directory.
Open Makefile and find the line where core-y is defined and add the directory test to the end of that line.
core-y += kernel/ mm/ fs/ test/ vpart_syscalls/
I then proceeded to build the kernel in a different fashion than is described there:
make localmodconfig
make menuconfig (making no changes)
make-kpkg clean
fakeroot make-kpkg --initrd --append-to-version=+tm kernel_image kernel_headers
cd ..
dpkg -i linux-image-3.8.*
dpkg -i linux-headers-3.8.*
The kernel that is installed boots fine. I made the following c program to test the syscall:
#include <stdio.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
int main(){
printk("Calling the new syscall!\n");
int ret = 100;
ret = syscall(349, 1, 2);
printf("call return value: %i\n", ret);
return 0;
}
When I compile and run this program, I get a return value of -1. I check the messages using dmesg and there is no evidence of my printk being called..
If anyone knows where my problem is I would be really really happy! I should say I am not too experienced at changing and building the kernel, but I have learned a lot about it. I read Robert Loves book - linux kernel development and several guides on the webs.
I think, the steps 3 and 4 may be incorrect for 64-bit kernels:
File 3: linux-x.x.x/arch/x86/kernel/syscall_table_32.S.
File 4: linux-x.x.x/arch/x86/include/asm/unistd_32.h
There are two files here: http://lxr.linux.no/linux+v3.2.41/arch/x86/kernel/
syscall_64.c 668 2008-12-24 14:26:58 -0800
syscall_table_32.S 8659 2012-01-04 14:55:50 -0800
First one defines syscall table contents for 64-bit mode using C file and macro-cheating with unistd_64.h
#define __SYSCALL(nr, sym) [nr] = sym,
const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
....
#include <asm/unistd_64.h>
};
Where asm/unistd_64.h is
#define __NR_read 0
__SYSCALL(__NR_read, sys_read)
and so on.
And second one, which you changed - is for 32-bit mode and written using asm file and labels (.long sys_call_name).
So, you defined syscall for 32-bit mode and you are using linux-image-3.2.0-4-rt-amd64 which is basically for " 64-bit PCs".
I think you compiled your test program as gcc test.c, which defaults to 64-bit mode. You can try -m32 option of gcc: gcc -m32 test.c to get 32-bit application (this will only work if you have correct cross environment for 32-bit builds) or compile this test on some 32-bit linux.
Or the other choice is to make step "4a": edit arch/x86/include/asm/unistd_64.h to add two lines:
#define __NR_insert_partition YOUR_NUMBER
__SYSCALL(__NR_insert_partition, insert_partition)
I'm not sure where and how NR_syscalls for 64bit is defined. It may be generated during build.
I have a project that requires a bunch of graphic files in the executable. Since there is no file system at the target I cant just use the fopen function. One way would converting the file content to a C source code that contains the variable definition like this
unsigned char file1_content[] = {
0x01, 0x02, ...
};
It's cumbersome to build such files even with a converter tool.
Is there any way to add binary files to the rdata section while specifying a variable name for each file? I think about using the linker script for this but didn't find a way.
It's not particularly cumbersome with a tool, and that's the classic solution. Search for "bin2c" to find some.
You simply need to include these "asset-building" steps in your build process, i.e. call the tool from the Makefile. This also means that the tool is only run if the source data has changed, which is nice.
At least the GNU linker (LD) seems capable of placing files in the sections of the output file (see the Section Placement documentation, like so:
.data : { afile.o bfile.o cfile.o }
But this sounds quite cumbersome, and it needs you to think about the sections of your executable file which often a bit too low-level. Also, it seems to require the input(s) to be object files, which kind of makes the problem circular since a generic binary asset isn't a linker-compatible object file.
I would recommend going with the bin2c approach.
You may use linker option --format along with -Wl, to pass it to linker, like:
gcc -Wl,--format=binary -Wl,myfile.bin -Wl,--format=default
Last setting format to default allows you to switch linker back to standard input format.
You may access your binary resources from sources via simple _binary_myfile_bin_start assembler symbol (for myfile.bin, for xxx.yyy it will be _binary_xxx_yyy_start and _binary_xxx_yyy_end) like:
extern uint8_t data[] asm("_binary_myfile_bin_start");
And next use data. It is much better then do objcopy by yourself, or use resource hacking.
UPD: Expanding with a little example -- main outputs first four bytes of its own object file:
#include "stdio.h"
#include "stdint.h"
extern uint8_t data[] asm("_binary_main_o_start");
int
main(void)
{
fprintf(stdout, "0x%x, 0x%x, 0x%x, 0x%x\n", data[0], data[1], data[2], data[3]);
return 0;
}
Now compile an run:
$ gcc -o main.o -c main.c
$ gcc -o main main.o -Wl,--format=binary -Wl,main.o -Wl,--format=default
$ ./main
0x7f, 0x45, 0x4c, 0x46
I am trying to set the sys exit call to a variable by
extern void *sys_call_table[];
real_sys_exit = sys_call_table[__NR_exit]
however, when I try to make, the console gives me the error
error: ‘__NR_exit’ undeclared (first use in this function)
Any tips would be appreciated :) Thank you
Since you are in kernel 2.6.x , sys_call_table isnt exported any more.
If you want to avoid the compilation error try this include
#include<linux/unistd.h>
however, It will not work. So the work around to "play" with the sys_call_table is to find the address of sys_call_table in SystemXXXX.map (located at /boot) with this command:
grep sys_call System.map-2.6.X -i
this will give the addres, then this code should allow you to modify the table:
unsigned long *sys_call_table;
sys_call_table = (unsigned long *) simple_strtoul("0xc0318500",NULL,16);
original_mkdir = sys_call_table[__NR_mkdir];
sys_call_table[__NR_mkdir] = mkdir_modificado;
Hope it works for you, I have just tested it under kernel 2.6.24, so should work for 2.6.18
also check here, Its a very good
http://commons.oreilly.com/wiki/index.php/Network_Security_Tools/Modifying_and_Hacking_Security_Tools/Fun_with_Linux_Kernel_Modules
If you haven't included the file syscall.h, you should do that ahead of the reference to __NR_exit. For example,
#include <syscall.h>
#include <stdio.h>
int main()
{
printf("%d\n", __NR_exit);
return 0;
}
which returns:
$ cc t.c
$ ./a.out
60
Some other observations:
If you've already included the file, the usual reasons __NR_exit wouldn't be defined are that the definition was being ignored due to conditional compilation (#ifdef or #ifndef at work somewhere) or because it's being removed elsewhere through a #undef.
If you're writing the code for kernel space, you have a completely different set of headers to use. LXR (http://lxr.linux.no/linux) searchable, browsable archive of the kernel source is a helpful resource.