ELF Header, are offset 06h and 14h duplicated? - linux

I would like to know if these 2 headers have the same meaning nor why?
From wikipedia :
offset 06h : Set to 1 for the original version of ELF.
offset 14h : Set to 1 for the original version of ELF.
reference : http://en.wikipedia.org/wiki/Executable_and_Linkable_Format

You may want to read a more detailed document which is likely to include the information you're looking for:
http://www.skyfree.org/linux/references/ELF_Format.pdf
The header structure
#define EINIDENT 16
typedefstruct{
unsigned char e_ident[EINIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32Ehdr;
The 2nd e_version which defines the version as 1 (i.e. "current")
e_version This member identifies the object file version.
Name Value Meaning
EV_NONE 0 Invalid version
EV_CURRENT 1 Current version
The value 1 signifies the original file format; extensions will
create new versions with higher numbers. The value of EV_CURRENT,
though given as 1 above, will change as necessary to reflect the
current version number.
The version in the e_ident part is also EV_CURRENT, so exactly the same version:
EI_VERSION Byte e_ident[EI_VERSION] specifies the ELF header version
number. Currently, this value must be EV_CURRENT, as
explained above for e_version.
From what I understand, I would say that the version has not changed yet so it is still 1 in both places, but that could change in the future...

Related

How to evaluate the flags field of mtd_info_user?

The MTD driver placed inside the Linux kernel source has a definition as below.
struct mtd_info_user {
__u8 type;
__u32 flags;
__u32 size; /* Total size of the MTD */
__u32 erasesize;
__u32 writesize;
__u32 oobsize; /* Amount of OOB data per block (e.g. 16) */
__u64 padding; /* Old obsolete field; do not use */
};
I'm trying to understand what the flags field stands for. My ultimate purpose is to find a way to check if the external MTD device is healthy. I thought that the flags field can represent the actual status of the device.
Inside the mtdchar_open(..) function from mtdchar.c source code, there is a comparison as below.
/* You can't open it RW if it's not a writeable device */
if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) {
ret = -EACCES;
goto out1;
}
So, I guess the flags field can be evaluated by using the macros from the mtd-abi.h header.
#define MTD_ABSENT 0
#define MTD_RAM 1
#define MTD_ROM 2
#define MTD_NORFLASH 3
#define MTD_NANDFLASH 4 /* SLC NAND */
#define MTD_DATAFLASH 6
#define MTD_UBIVOLUME 7
#define MTD_MLCNANDFLASH 8 /* MLC NAND (including TLC) */
#define MTD_WRITEABLE 0x400 /* Device is writeable */
#define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */
#define MTD_NO_ERASE 0x1000 /* No erase necessary */
#define MTD_POWERUP_LOCK 0x2000 /* Always locked after reset */
The problem is about why some of those definitions are declared like normal integers, e.g. MTD_ABSENT.

Where is Import Table in ELF file?

I found ".dynsym" in String Table, got index.
Then I found section with sh_name = index && sh_type = SHT_DYNSYM.
So I got sh_offset = 464 and sh_size = 64.
But you can see in the attached picture, that on the offset 464 there are only zeros.
I suppose that Import Table starts on offset 528. Question is: how calculate it %)
But you can see in the attached picture, that on the offset 464 there are only zeros.
Wrong: 01, 20, 29, 12 etc. are not "only zeros" last time I checked.
I suppose that Import Table starts on offset 528
No, it does not. For some reason you are expecting to find a Microsoft PE-style import table in an ELF file. It's not there.
An equivalent of an import table in ELF is contained in two tables. One contains Elf{32,64}_Sym fixed-size records:
typedef struct
{
Elf32_Word st_name; /* Symbol name (string tbl index) */
Elf32_Addr st_value; /* Symbol value */
Elf32_Word st_size; /* Symbol size */
unsigned char st_info; /* Symbol type and binding */
unsigned char st_other; /* Symbol visibility */
Elf32_Section st_shndx; /* Section index */
} Elf32_Sym;
and is contained in the .dynsym section.
The other table is contained in .dynstr section (which, in your file starts at offset 528), and has just the (variable-size) strings separated by NUL character.
The .st_name in the first table refers to offset in .dynstr.

How to get the name of a segment by using its `Elf64_Phdr` program header?

As I know, a ELF object consists of a number of segments, each of which has a corresponding program header describing the segment. In libelf, a program header is defined as a Elf64_Phdr (or Elf32_Phdr) structure, and a Elf64_Phdr structure is defined like this:
typedef struct {
Elf32_Word p_type; /* Segment type */
Elf32_Off p_offset; /* Segment file offset */
Elf32_Addr p_vaddr; /* Segment virtual address */
Elf32_Addr p_paddr; /* Segment physical address */
Elf32_Word p_filesz; /* Segment size in file */
Elf32_Word p_memsz; /* Segment size in memory */
Elf32_Word p_flags; /* Segment flags */
Elf32_Word p_align; /* Segment alignment */
} Elf32_Phdr;
However, segments have names (don't they?) and Elf64_Phdr structures don't have a field which points to their corresponding names. So, how to get a name of a segment of an ELF file from its corresponding program header? Or is the p_type field enough to identify a segment, so that segments don't have names?
However, segments have names (don't they?)
No, they don't.
Or is the p_type field enough to identify a segment, so that segments don't have names?
Correct.

Linux sys_call_table rip relative addressing x86_64

I am trying to get offset of sys_call_table on Linux x86_64.
First of all I read pointer to system_call entry by reading it from MSR_LSTAR and it's correct
static unsigned long read_msr(unsigned int msr)
{
unsigned low, high;
asm volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
return ((low) | ((u64)(high) << 32));
}
Then I parse it to find opcode of call instruction and it is also correct
#define CALL_OP 0xFF
#define CALL_MODRM 0x14
static unsigned long find_syscall_table(unsigned char *ptr)
{
//correct
for (; (*ptr != CALL_OP) || (*(ptr+1) != CALL_MODRM); ptr++);
//not correct
ptr += *(unsigned int*)(ptr + 3);
pr_info("%lx", (unsigned long)ptr);
return ptr;
}
But I failed to get address after call opcode. First byte of ptr is opcode, then ModRM byte, then SIB and then 32bit displacement, so I add 3 to ptr and dereferenced it as integer value and then add it to ptr, because it is %RIP, and address is RIP relative. But the result value is wrong, it don't coincide with value I see in gdb, so where am I wrong?
It's not x7e9fed00 but rather -0x7e9fed00 - a negative displacement.
That is the sign-magnitude form of the 2's complement negative number 0x81601300
which is stored by a little-endian processor as "00 13 60 81"
No idea if you will find sys_call_table at the resulting address however. As an alternative idea, it seems some people find it by searching memory for the known pointers to functions that should be listed in it.

Why is the program header executable?

I used readelf on several binaries on my linux box and saw something that surprised me in the program headers. This eample is from the 'ld' utility, but it also occurs with anything I compile with gcc.
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
This segment spans the entirety of the program headers. Why is is marked as executable? It doesn't contain machine code. But also, why is even this present in the headers? I don't really want it in my program image.
The PHDR pointing to the PHDRs tells the loader that the PHDRs themselves should be mapped to the process address space, in order to make them accessible to the program itself.
This is useful mainly for dynamic linking.
The reason the memory is marked as executable is because the PHDRs are smaller than one page, and live right next to the start of the executable code. If the permissions for the PHDRs were different from those of the program text, the linker would have to insert padding between them.
The main File ELF headers are there to easily find the offset in the file where other sections are stored. Then each subheader describes the data in it's section.
Main ELF header looks like this:
/* ELF File Header */
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf32_Half e_type; /* Object file type */
Elf32_Half e_machine; /* Architecture */
Elf32_Word e_version; /* Object file version */
Elf32_Addr e_entry; /* Entry point virtual address */
Elf32_Off e_phoff; /* Program header table file offset */
Elf32_Off e_shoff; /* Section header table file offset */
Elf32_Word e_flags; /* Processor-specific flags */
Elf32_Half e_ehsize; /* ELF header size in bytes */
Elf32_Half e_phentsize; /* Program header table entry size */
Elf32_Half e_phnum; /* Program header table entry count */
Elf32_Half e_shentsize; /* Section header table entry size */
Elf32_Half e_shnum; /* Section header table entry count */
Elf32_Half e_shstrndx; /* Section header string table index */
} Elf32_Ehdr;
The program header(s) are there because they describe the executable parts of the ELF executable.
The next portion of the program are
the ELF program headers. These
describe the sections of the program
that contain executable program code
to get mapped into the program address
space as it loads.
/* Program segment header. */
typedef struct
{
Elf32_Word p_type; /* Segment type */
Elf32_Off p_offset; /* Segment file offset */
Elf32_Addr p_vaddr; /* Segment virtual address */
Elf32_Addr p_paddr; /* Segment physical address */
Elf32_Word p_filesz; /* Segment size in file */
Elf32_Word p_memsz; /* Segment size in memory */
Elf32_Word p_flags; /* Segment flags */
Elf32_Word p_align; /* Segment alignment */
} Elf32_Phdr;
This is taken from here

Resources