What is installed in the target file?

Source: Internet
Author: User
Tags field table

Understanding the status and attributes of various variables in the program in the compilation and running stages is very beneficial for our development program. Through the discussion of the following examples, figuring out what information is contained in the target file can help us understand the impact of various storage classes in the C language on the program, and let us be confident when writing a program. As said, a real programmer must be familiar with every byte of his program.

Let's take a look at the following program code:

/* Simple_section.c */

 

Int printf (const char * format,...); // too lazy to include the header file. Just declare printf.

 

Int global_init_var = 1; // initialized global variable
Int global_uninit_var; // uninitialized global variable

 

Void
Func (int I)
{
Printf ("% d/N", I );
}

 

Int
Main (void)
{
Static int static_init_var = 2; // initialized static local variable
Static int static_uninit_var; // uninitialized static local variable

Int A = 3; // initialized local variable
Int B; // uninitialized local variable

 

Func (static_init_var + static_uninit_var + A + B );
Return;
}

We know that for initialized global variables and static local variables, they are stored by the compiler in the executable target file during compilation. for non-initialized global variables and static local variables, the space is not allocated during compilation, but only in. mark them in the BSS segment. When the program runs, it allocates space for them in the memory and initializes them to zero.

Next we will compile the above Code with GCC, and use option-C to obtain a relocated target file.Simple_section.o, Use the objdump tool to view it, as shown below:

The option-H in the objdump command prints the basic information of each segment in the ELF File. Of course, you can use the-x option to print more detailed information.

We can see that unlinked relocatable files include the ones we are familiar. text Segment ,. data segment. The size field indicates the size of each segment. file off indicates the offset of each segment relative to the file header ,. the offset of the text segment is 0x000034, that is, 52 bytes. These 52 bytes store the ELF File Header, also known as the elf header. The. Text Segment starts from 53rd bytes, which stores all the machine commands compiled in the source program.

The. Data Segment begins with the 0x85 byte, which stores all the static local variables initialized in the source program and the initialized global variables. We can see that this segment has a total of 8 bytes, respectively storing the global variables in the program.Global_init_varAnd static local variablesStatic_init_var.. The rodata segment stores read-only data in the program. The so-called read-only data includes string constants, Integer constants, and floating point constants. The figure shows that the. rodata segment contains a total of four bytes, including the string "% d/n" in the printf statement and a total of four bytes (including the string Terminator '/0 ').

The size of the. BSS segment is 4 bytes, but we know that the. BSS segment does not occupy storage space. The size of the 4 bytes here is just a description and does not occupy disk space. The three BSS letters mean block started by symbol. We can also remember it as better save space, which is used to save space, we can also see in the attribute information of each field, in addition. each segment outside the BSS segment has the contents attribute. Contents indicates that this segment is the actual content in the disk file. However. BSS only has the alloc attribute and does not occupy space in the file. The reason for this is that it is unnecessary for them (all uninitialized global variables and all uninitialized static local variables) disk space allocation. Because they are not initialized, the system will Initialize all of them to 0 by default when running the program. Since they are all 0, there is no need to put a bunch of 0 in the disk, just remember how many bytes of memory they need to run.

Note that the size in the. BSS segment is 4 bytes, and our program has an uninitialized global variable.Global_uninit_varAnd an uninitialized static local variableStatic_uninit_var, It takes 8 bytes. Where are 4 bytes missing? To solve this problem, we need more information. We can use readelf to view more interesting and detailed information. readelf is a very useful tool, it can be used to conveniently view the internal information of the ELF File. We use the-s option to preview all the file segments:

 

The output result is the content of the ELF File field table. As you can see, there are other auxiliary fields besides the basic segments seen by the objdump tool. the symtab field stores the basic attributes of each segment in the ELF File, such as the segment name, length, and offset in the file.

This field table is based on a struct array. This struct is stored in/usr/include/elf. elf32_shdr is defined in H. During program compilation, this struct is used to correspond to each segment of the target file. Each elf32_shdr struct corresponds to a segment. Therefore, elf32_shdr is also called a segment descriptor, in this example, a field table is a struct array with 11 elements (the first element is an invalid segment descriptor ). The struct is as follows:

/* Section header .*/

Typedef struct
{
Elf32_word sh_name;/* section name (string TBL index )*/
Elf32_word sh_type;/* section type */
Elf32_word sh_flags;/* Section flags */
Elf32_addr sh_addr;/* Section virtual ADDR at execution */
Elf32_off sh_offset;/* section File offset */
Elf32_word sh_size;/* section size in bytes */
Elf32_word sh_link;/* link to another section */
Elf32_word sh_info;/* additional section information */
Elf32_word sh_addralign;/* Section alignment */
Elf32_word sh_entsize;/* entry size if section holds table */
} Elf32_shdr;

We can see that each member corresponds to each column (except the first column, the number indicates the array subscript) (not the one-to-one correspondence ). Next we will use the-s option to see the specific content of the symbol table field. symtab:

Note that static local variables are not initializedStatic_uninit_varIt is placed in the segment where the array subscript is 4, that is, the. BSS segment, but the global variable is not initialized.Global_uninit_varIt is put in a file called COM, just an undefined common symbol. The processing of the compiler depends on the specific implementation. The results of different systems may be different. This issue is related to strong and weak symbols. The reason is that the CompilerGlobal_uninit_varAs a result, the. BSS is only marked with four bytes.

Segment tables are also very important to relocate tables, such as the above. rel. text, this is called the relocation table of the code segment. Other segments can also have the relocation table, but this example is relatively simple, only the relocation table of the code segment appears, if the data segment. data also needs to be relocated, so it will appear in the ELF File. rel. data Segment.

Of course, the role of table relocation is to relocate the table. The reason is that when several target files are combined to become one that can be loaded and executed by the OS, the segments between them need to be combined again. For example, if the segments of each file are merged and the data segments of each file are merged, data will be moved, for example, if a function originally located at a position in the code segment is relocated to another place, if other parts of the program do not know about this, the code that calls the function will certainly not be located in the north in the future, therefore, it is necessary to store the moving information of each segment in each target file that needs to be moved in one place before the link, so that there is a root cause for the link, so as not to get confused. This is the relocation segment.

The ELF file has a 52-byte ELF File Header, as shown in the following code:

This ELF File Header stores a lot of information. The preceding figure shows the elf Phantom number, file length and byte length, data storage method, version, running platform, and Abi, elf relocation type, hardware platform, hardware platform version, entry address, program header entry and length, field table location and length, and segment quantity.

The first four bytes in the magic number must be the same identifier for all elf files. 0x7f 0x45 0x4c 0x46. When the OS loads executable files, it checks whether the magic number is correct. If it is incorrect, it rejects the loading. The next byte is used to identify the file class of the ELF File. 0x01 represents 32-bit, and 0x02 represents 64-bit. The next byte is used to indicate the byte order of the file. 1 indicates the small end and 2 indicates the large end. Next, the main version number of the ELF file, which is generally 1. The elf standard has not been upgraded since version 1.2. The rest are retained.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.