How can I find the size of a ELF file/image with Header information?
Asked Answered
E

6

5

I need to find the size of an elf image for some computation. I have tried with the readelf utility on linux which gives the informations about the headers and section. I need to have the exact file size of the elf(on the whole).

How do I find the size of the ELF from the header information or Is there any other means to find the size of an elf without reading the full image.

Excel answered 8/6, 2010 at 7:5 Comment(2)
The e_ehsize field contains only the size of the executable header, not the size of the actual file, but you could ofcourse use the offset to section header table since it is at the very end of the binary and the offset is in-file (not virtual). So calculate e_shoff + [number_of_sectionheaders * sizeof(Elf32_Shdr)]Rosaliarosalie
To clarify stuff, the number of section headers should be found in the field e_shnum, the size IIRC in the field e_shentsizeRosaliarosalie
L
-3

You can use the stat functions family (stat(), lstat(), fstat()) to get the size of any file (using the st_size member of the stat member). Do you need something more specific?


If you really want to use the ELF structure, use the elf.h header which contains that structure:

typedef struct {
         unsigned char  e_ident[EI_NIDENT];
         uint16_t       e_type;
         uint16_t       e_machine;
         uint32_t       e_version;
         ElfN_Addr      e_entry;
         ElfN_Off       e_phoff;
         ElfN_Off       e_shoff;
         uint32_t       e_flags;
         uint16_t       e_ehsize;
         uint16_t       e_phentsize;
         uint16_t       e_phnum;
         uint16_t       e_shentsize;
         uint16_t       e_shnum;
         uint16_t       e_shstrndx;
 } Elf32_Ehdr;

It's the header of an ELF32 file (replace 32 with 64 for a 64-bit file). e_ehsize is the size of the file in bytes.


I'll copy verbatim the comment that was posted as an edit suggestion:

This answer is incorrect. e_ehsize is merely the size of the elf header, not the elf file.

Locally answered 8/6, 2010 at 7:8 Comment(3)
How do we use this structure to find the size of any elf file.. I mean API kind of stuff..Excel
What is your language? In C for example it should be pretty easy to read the header with fread(), then print the e_ehsize member.Pigfish
The e_ehsize is the size of ELF header which is 64 Bytes for 64-bit and 52 Bytes for 32-bit format.Concertgoer
B
6

The answer to the specific question is a little tricky for ELF files.

The following will compute the size of the "descriptive" information in an ELF file using the header: e_ehsize + (e_phnum * e_phentsize) + (e_shnum * e_shentsize)

The above is based on the ELF documentation.

The next piece to add to the above sum is the size in the file of the section entries. Intuitively we would like to compute this using sh_size for each of the sections in the file -- e_shnum of them. HOWEVER, this doesn't yield the correct answer due to alignment issues. If you use an ordered list of sh_offset values you can compute the exact number of bytes that the section entry occupies (I found some strange alignments where using sh_addralign isn't as useful as you would like); for the last section entry use the file header's e_shoff since the section header table is last. This worked for the couple I checked.

update.c in libelf has the details it uses when updating an elf file.

Burley answered 22/2, 2012 at 23:54 Comment(3)
The elf_getphdrnum() and elf_getshdrnum() functions are recommended for retrieving the number of PHDR and SHDR entries in the ELF object respectively. These functions correctly handle ELF objects that use extended numbering, where the direct use of the e_phnum or e_shnum fields of the ELF header is likely to be incorrect.Matthei
But since the section header table maps straight across, and the ordered list of sh_offsets are expanded and mapped into memory, the section header table will not end up being at the end of the memory image. For example on disk sh_offset will be smaller than the last section's memory image offset. small - big = negativeSiftings
Can ELF file of any supported type have data chunk not within boundaries of that file any section?Opal
F
4

Example:

ls -l gives 126584

Calculation using the values also reported by readelf -h:

Start of section headers    e_shoff     124728
Size of section headers     e_shentsize 64
Number of section headers   e_shnum     29

e_shoff + ( e_shentsize * e_shnum ) = 126584

This assumes that the section header table (SHT) is the last part of the ELF. This is usually the case but it could also be that the last section is the last part of the ELF. This should be checked for, but is not in this example.

Here is a working implementation in C, compile with gcc elfsize.c -o elfsize:

#include <elf.h>
#include <byteswap.h>
#include <stdio.h>
#include <stdint.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

typedef Elf32_Nhdr Elf_Nhdr;

static char *fname;
static Elf64_Ehdr ehdr;
static Elf64_Phdr *phdr;

#if __BYTE_ORDER == __LITTLE_ENDIAN
#define ELFDATANATIVE ELFDATA2LSB
#elif __BYTE_ORDER == __BIG_ENDIAN
#define ELFDATANATIVE ELFDATA2MSB
#else
#error "Unknown machine endian"
#endif

static uint16_t file16_to_cpu(uint16_t val)
{
    if (ehdr.e_ident[EI_DATA] != ELFDATANATIVE)
        val = bswap_16(val);
    return val;
}

static uint32_t file32_to_cpu(uint32_t val)
{
    if (ehdr.e_ident[EI_DATA] != ELFDATANATIVE)
        val = bswap_32(val);
    return val;
}

static uint64_t file64_to_cpu(uint64_t val)
{
    if (ehdr.e_ident[EI_DATA] != ELFDATANATIVE)
        val = bswap_64(val);
    return val;
}

static long unsigned int read_elf32(int fd)
{
    Elf32_Ehdr ehdr32;
    ssize_t ret, i;

    ret = pread(fd, &ehdr32, sizeof(ehdr32), 0);
    if (ret < 0 || (size_t)ret != sizeof(ehdr)) {
        fprintf(stderr, "Read of ELF header from %s failed: %s\n",
            fname, strerror(errno));
        exit(10);
    }

    ehdr.e_shoff        = file32_to_cpu(ehdr32.e_shoff);
    ehdr.e_shentsize    = file16_to_cpu(ehdr32.e_shentsize);
    ehdr.e_shnum        = file16_to_cpu(ehdr32.e_shnum);

    return(ehdr.e_shoff + (ehdr.e_shentsize * ehdr.e_shnum));
}

static long unsigned int read_elf64(int fd)
{
    Elf64_Ehdr ehdr64;
    ssize_t ret, i;

    ret = pread(fd, &ehdr64, sizeof(ehdr64), 0);
    if (ret < 0 || (size_t)ret != sizeof(ehdr)) {
        fprintf(stderr, "Read of ELF header from %s failed: %s\n",
            fname, strerror(errno));
        exit(10);
    }

    ehdr.e_shoff        = file64_to_cpu(ehdr64.e_shoff);
    ehdr.e_shentsize    = file16_to_cpu(ehdr64.e_shentsize);
    ehdr.e_shnum        = file16_to_cpu(ehdr64.e_shnum);

    return(ehdr.e_shoff + (ehdr.e_shentsize * ehdr.e_shnum));
}

long unsigned int get_elf_size(char *fname)
/* TODO, FIXME: This assumes that the section header table (SHT) is
the last part of the ELF. This is usually the case but
it could also be that the last section is the last part
of the ELF. This should be checked for.
*/
{
    ssize_t ret;
    int fd;
    long unsigned int size = 0;

    fd = open(fname, O_RDONLY);
    if (fd < 0) {
        fprintf(stderr, "Cannot open %s: %s\n",
            fname, strerror(errno));
        return(1);
    }
    ret = pread(fd, ehdr.e_ident, EI_NIDENT, 0);
    if (ret != EI_NIDENT) {
        fprintf(stderr, "Read of e_ident from %s failed: %s\n",
            fname, strerror(errno));
        return(1);
    }
    if ((ehdr.e_ident[EI_DATA] != ELFDATA2LSB) &&
        (ehdr.e_ident[EI_DATA] != ELFDATA2MSB))
    {
        fprintf(stderr, "Unkown ELF data order %u\n",
            ehdr.e_ident[EI_DATA]);
        return(1);
    }
    if(ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
        size = read_elf32(fd);
    } else if(ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
        size = read_elf64(fd);
    } else {
        fprintf(stderr, "Unknown ELF class %u\n", ehdr.e_ident[EI_CLASS]);
        return(1);
    }

    close(fd);
    return size;
}

int main(int argc, char **argv)
{
    ssize_t ret;
    int fd;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <ELF>\n", argv[0]);
        return 1;
    }
    fname = argv[1];

    long unsigned int size = get_elf_size(fname);
    fprintf(stderr, "Estimated ELF size on disk: %lu bytes \n", size);
    return 0;
}
Fruge answered 18/9, 2016 at 14:7 Comment(0)
S
0

Perhaps gelf could be useful.

GElf is a generic, ELF class-independent API for manipulat- ing ELF object files. GElf provides a single, common inter- face for handling 32-bit and 64-bit ELF format object files.

specifically these functions:

elf32_fsize, elf64_fsize - return the size of an object file type

Sanasanabria answered 8/6, 2010 at 7:29 Comment(2)
I cannot go with this as I need to install the library stuffs in the Root file system that would take more space..Excel
@fasil: You could use the "libelf by Example" tutorial for getting started with the GELF(3) API.Matthei
D
0

Have you tried using the gnu "readelf" utility?

http://sourceware.org/binutils/docs/binutils/readelf.html

Dissimulate answered 8/6, 2010 at 7:33 Comment(0)
C
0

All you have to do is to sum the last section's file offset and its size.

fseek(fileHandle, elfHeader.e_shoff + (elfHeader.e_shnum-1) * elfHeader.e_shentsize, SEEK_SET);
Elf64_Shdr sectionHeader; // or Elf32_Shdr
fread(&sectionHeader, 1, elfHeader.e_shentsize, fileHandle);

int fileSize = sectionHeader.sh_offset + sectionHeader.sh_size;

elfHeader used values:

e_shoff = Section header table file offset
e_shnum = Section header table entry count
e_shentsize = Section header table entry size       

sectionHeader used values:

sh_offset = Section file offset
sh_size = Section size in bytes
Chiapas answered 9/8, 2016 at 13:42 Comment(2)
May ELF file have data chunks within boundaries of none of its sections?Opal
Even if section header table is not the last section in ELF file as it used to be is it guaranteed all sections are ordered in section header table by their offsets in file?Opal
L
-3

You can use the stat functions family (stat(), lstat(), fstat()) to get the size of any file (using the st_size member of the stat member). Do you need something more specific?


If you really want to use the ELF structure, use the elf.h header which contains that structure:

typedef struct {
         unsigned char  e_ident[EI_NIDENT];
         uint16_t       e_type;
         uint16_t       e_machine;
         uint32_t       e_version;
         ElfN_Addr      e_entry;
         ElfN_Off       e_phoff;
         ElfN_Off       e_shoff;
         uint32_t       e_flags;
         uint16_t       e_ehsize;
         uint16_t       e_phentsize;
         uint16_t       e_phnum;
         uint16_t       e_shentsize;
         uint16_t       e_shnum;
         uint16_t       e_shstrndx;
 } Elf32_Ehdr;

It's the header of an ELF32 file (replace 32 with 64 for a 64-bit file). e_ehsize is the size of the file in bytes.


I'll copy verbatim the comment that was posted as an edit suggestion:

This answer is incorrect. e_ehsize is merely the size of the elf header, not the elf file.

Locally answered 8/6, 2010 at 7:8 Comment(3)
How do we use this structure to find the size of any elf file.. I mean API kind of stuff..Excel
What is your language? In C for example it should be pretty easy to read the header with fread(), then print the e_ehsize member.Pigfish
The e_ehsize is the size of ELF header which is 64 Bytes for 64-bit and 52 Bytes for 32-bit format.Concertgoer

© 2022 - 2024 — McMap. All rights reserved.