Difference between vmlinux and vmlinux.o - linux-kernel

When I build the Linux kernel, two images are generated vmlinux and vmlinux.o. They both seem to differ in size as well (113KB and 198KB respectively...). Could someone provide insight into the differences ?
Thanks,
Vj

The images produce during a Linux build vary by architecture and target. There are many intermediate build targets besides those two mentioned in the question. Most are uninteresting except possibly for academic purposes. Unfortunately, there is more than one target named vmlinux. vmlinux.o is not very interesting. At the top level Linux tree, you will find an ELF file called vmlinux. Executing
$ file vmlinux
should confirm that this is the ELF file. I don't know of any systems that boot this file directly. The only time this file is interesting is for debugging, because it contains debug symbols that a debugger can read. The actual boot target will be found in a subdirectory depending on architecture. For x86, (thought that's not my expertise) I think you'll find a target called bzImage. For ARM architectures, some systems boot zImage, others boot uImage (which is a Linux kernel image packaged in a header that the U-Boot bootloader recognizes. Even if you remove the U-Boot header, the image is a composite image. That is, it's not an ELF file, and it's not a pure .o, etc. It is a concatenation of several binary blobs, which can include kernel configuration information, the kernel itself, almost always compressed, and often a piece of runnable code (ie. not compressed) that I call a "bootstrap" loader, which often contains machine and board-specific initialization routines. I'm less familiar with x86, but even on that architecture, the kernel boot image (the one that you boot) is a composite image containing several components, ie. not a pure .o or ELF file.
One good way to see what is happening is to compile your kernel with verbose mode, and then watch the final steps to see how the images are manipulated. Add V=1 to the 'make' command line to turn on verbose mode.
Happy hacking!

When the Linux kernel is build, two images are generated vmlinux and vmlinux.o.
vmlinux.o : Is Relocatable object file
vmlinux : Is Executable file
Linker takes relocatable object files and command line arguments in order to generate an executable object file. To produce an executable file the Linker has to perform the symbol resolution, and Relocation.
Perform ‘file’ and ‘readelf’ command on vmlinux.o and vmlinux for more info.
root#beaglebone:/home# file vmlinux
vmlinux: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, BuildID[sha1]=0xdfd102a3c2b79fcc2f1949323dc54b9371c75608, not stripped
root#beaglebone:/home#
root#beaglebone:/home# file vmlinux.o
vmlinux.o: ELF 32-bit LSB relocatable, ARM, version 1 (SYSV), not stripped

Try the following to find out what they are.
file vmlinux
file vmlinux.o
Check your make file to find out how vmlinux is prepared. This will shed some light.
It is not necessary that if vmlinux.o is used to prepare vmlinux, the size of vmlinux must be greater than vmlinux.o

Related

When are the contents of .exit.text section in an ARM vmlinux file discarded once it is loaded in memory?

I understand that the .exit.text section will be filled by the linker with functions defined with __exit macro. I can see the section on dissassembly of the vmlinux file. But I did not understand at what point are the contents discarded once the file is loaded in memory? Does it happen in the kernel code? Can anyone explain this more?
Thanks in advance!
The files vmlinux.lds.S and module.c handle this. The handling depends on your kernel version and configuration; neither have been given. My assumption is you mean the .exit.text section in the kernel and not some user space task. Generally, the kernel doesn't exit, so they are discarded by the linker script unless you have some debugging configurations.
Edit: The android kernel was made with a .config file which enables Linux kernel features at compile time. The .config for CONFIG_HOTPLUG_CPU is a CPU; some big servers can keep running even when the CPU is exchanged. It is hard to answer your question. I don't know where your Android kernel source is or what .config options it was built with.
The sections are kept with GENERIC_BUG; so it is possible your kernel was built with this. From the stock vmlinux.lds.S, the .exit.data section is put before __init_end, so it is freed and returned to memory after the init portion runs. Ie, present only during boot. Under these circumstances, you will see it in the vmlinux ELF, but not in the runtime kcore or however you are dumping it.
Specifically, main.c's start_kernel(), rest_init(), kernel_init(), and free_initmem() are the place where this stuff is discarded.

Changing linux kernel system call number

I wanted to build my own custom kernel with a different syscall table. (same syscalls but in different position/numbers)
I was working on kernel 3.2.29.
Changing the kernel was quite easy:
1) changing the syscall position in ‫‪arch/x86/kernel/syscall_table_32.S‬‬
2) changing the syscall macro number in arch/x86/include/asm/unistd_32.h
3) compiling and installing the new kernel
I switched the syscalls around: sys_open took the place and number of sys_read, and vice versa.
I figured that if I compile glibc with the modified kernel headers, I could have a running system, but unfortunately, it wasn't enough and my system won't boot.
Am I missing something? What else do I need to do in order to have a running system?
The steps I have taken are:
1) building and installing the kernel as described in my question
2) extracting the new kernel headers using make headers_install INSTALL_HDR_PATH=[path]
3) building glibc with the parameter --with-headers=[path/include]
4) I used a live cd to access the file system externally in order to install the new glibc, using the make install install_root=[the original file system] (so the system won't break during the install)
I hope that the new glibc was built properly, but I am not sure.
After that, when booting the system, the boot stops in the (initrafms) shell screen:
I guess I need to rebuild the initrd, but how do I compile it according to the new syscall table?
You will have to rebuild everything. Even if all your binaries are dynamically linked, it is possible that the old syscalls were inlined into the binary because many of the C functions are just return syscall(__NR_somecall,...).
You could do this manually, but it could be difficult to keep the toolchains straight unless you use a cross compilable toolchain like buildroot, aboriginal or similar. Pick whichever best suits you (I prefer Rob Landley's aboriginal - http://landley.net/aboriginal/ )
Then to make your initrd just expand the old one using {z,bz,xz}cat oldinit.rd |cpio -id; rm oldinit.rd. Replace the old kernel modules, libs and binaries with the new and cpio and compress it back (cpio needs the -H newc option) ... or now you can rebuild your kernel and point the initramfs to that directory, but wouldn't recommend that if your initrd may need changed frequently such as if for instance you were testing out a whole new syscall structure and having to debug a lot.
Scrambling the system call numbers is really going to hurt. You'll at least need to rebuild all of the statically linked binaries on your system and your initrd (if you use one).
You haven't said at what point the boot fails, but even if the kernel comes up it is likely that the critical programs contained in the initrd compressed ramdisk would fail because they have the original syscall numbers hard-coded. You will need to rebuild and repackage those as well.
You might consider first replacing init with a static hello-world type of program to verify that your kernel can support a userspace at all; then look into the details of making all the complexity of a modern linux userspace match.
you had to learn to reading the messsage of pansic dump and show us what kenrel panic. Without this information, people can hardly help you or provide you useful suggestion.

Qemu arm Linux kernel boot debug, no source code

I am using Qemu to learn some linux kernel development/hacking and wanted to debug the boot process of Linux (2.6.34.3). I have compiled for the ARM versatile platform and is using Codesourcerys arm-none-eabi crosscompiler. I am using Eclipse as the environment to build and debug using gdbserver.
So I have manged to successfully build and run the kernel in qemu but the problem is that I dont see any source code in the debugger at the boot process(at address 0), I can only see the disassembly code. However, when it switches to virtual memory at init/main.c (address over 0xC0000000), the source code appears and I can see the source code and step through and over code. Why is that? I want that from the beginning.
Anyone have any tips on how to debug the boot process of Linux? All the guides in google shows how to debug the kernel, but they all show from start_kernel() (located in init/main.c) and not from the beginning of the boot process (in arch/arm/boot/compressed/head.S). Anyone with experience help please, thank you!
Looked into the System.map in the root folder and there is only symbols for stuff from c0004000 (where the virtual address start). I load vmlinux into gdbserver to get debug information, Maybe thats why theres no source?
The Linux kernel uses a 2-step booting processing (and this does not include any boot loader like u-Boot ...). You can better understand this especially by looking into 2 .lds files (detailed below) for linking:
arch/arm/boot/compressed/vmlinux.lds.in, which generates arch/arm/boot/compressed/vmlinux.lds.
Along with other .o files in arch/arm/boot/compressed, a vmlinux is generated inside this folder.
You can use arm-none-eabi-nm -a -n arch/arm/boot/compressed/vmlinux to see the symbols for this stage. All addresses are physical addresses.
These symbols are NOT included in System.map
The second vmlinux is generated by kernel .o files and arch/arm/kernel/vmlinux.lds (note: the path is different)
I hope this explains why you can not see the booting source code in Eclipse.
linux kernel is too complex to understand(for a beginner).
Why dont use use a smaller OS like xv6:
OS is small, sourcecode is about 8000 lines
used by many universities
based on V6(unix),
boot process is the same except that its less complicated than that of linux.
Appendix B of the xv6 book deals with boot process(its short and sweet).You can run gdb on qemu and see the boot process, the main files to check out for are bootasm.S(in assembler) and bootmain.c.
This is much simpler and easier to do and understand when compared to linux.(atleast for beginners).There are assingmennts on , setting up qemu , using gdb ,tracking the boot process , doing changes to the source code etc in the link given.Give it a shot :)
Cheers,
sharan
head.S is written in assembly, not C. That's what the .S suffix indicates.

Creating ELF image

I need to create an ELF image file from shared objects (.so files) and write it to another partition in Windows. Then open this partition in Linux and load the shared objects.
Does anybody know how to create an ELF image (a bundle of many shared objects) in Windows?
You can use Cygwin and try a suitable GCC cross-toolchain. Perhaps you'll have to build it yourself first (which is troublesome), but there it goes...
EDIT:
Okay, here you are:
A simplified one:
Building GCC cross compiler (from "Linux" to "Windows") -- the basic steps are the same as described there. You'll just need to ./configure it with relevant --host=... and --target=.... And oh! Don't forget to set the build root, since building "in the source tree" is not supported -- you'll just get stuck in errors if you try (I did...)
A killer one:
http://cygwin.wikia.com/wiki/How_to_install_a_newer_version_of_GCC#Build_and_Install_GCC -- a complete guide.
Nowadays Linux understands NTFS. At least, it should be able to read off it.
You can also use a flash stick formatted as FAT32 or NTFS as the shared storage.
You can also run Linux in a VM and set up FTP server on it and exchange files through it.
There're many ways of sharing data between different OSes.

what's in a .exe file?

So a .exe file is a file that can be executed by windows, but what exactly does it contain? Assembly language that's processor specific? Or some sort of intermediate statement that's recognized by windows which turns it into assembly for a specific processor? What exactly does windows do with the file when it "executes" it?
MSDN has an article "An In-Depth Look into the Win32 Portable Executable File Format" that describes the structure of an executable file.
Basically, a .exe contains several blobs of data and instructions on how they should be loaded into memory. Some of these sections happen to contain machine code that can be executed (other sections contain program data, resources, relocation information, import information, etc.)
I suggest you get a copy of Windows Internals for a full description of what happens when you run an exe.
For a native executable, the machine code is platform specific. The .exe's header indicates what platform the .exe is for.
When running a native .exe the following happens (grossly simplified):
A process object is created.
The exe file is read into that process's memory. Different sections of the .exe (code, data, etc.) are mapped in separately and given different permissions (code is execute, data is read/write, constants are read-only).
Relocations occur in the .exe (addresses get patched if the .exe was not loaded at its preferred address.)
The import table is walked and dependent DLL's are loaded.
DLL's are mapped in a similar method to .exe's, with relocations occuring and their dependent DLL's being loaded. Imported functions from DLL's are resolved.
The process starts execution at an initial stub in NTDLL.
The initial loader stub runs the entry points for each DLL, and then jumps to the entry point of the .exe.
Managed executables contain MSIL (Microsoft Intermediate Language) and may be compiled so they can target any CPU that the CLR supports. I am not that familiar with the inner workings of the CLR loader (what native code initially runs to boot strap the CLR and start interpreting the MSIL) - perhaps someone else can elaborate on that.
I can tell you what the first two bytes in .exe files contain - 'MZ'. i mean the characters 'MZ'.
It actually represents: Mark Zbikowski. The guy who designed the exe file format.
http://en.wikipedia.org/wiki/Mark_Zbikowski
1's and 0's!
This wikipedia link will give you all the info you need on the Portable Executable format used for Windows applications.
An EXE file is really a type of file known as a Portable Executable. It contains binary data, which can be read by the processor and executed (essentially x86 instructions.) There's also a lot of header data and other miscellaneous content. The actual executable code is located in a section called .text, and is stored as machine instructions (processor specific). This code (as well as other parts of the .EXE) are put into memory, and the CPU is sent to it, where it starts executing. (Note that there's much more interfaces actually happening; this is a simplified explanation).

Resources