Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add file offset and memory alignment for the ELF segments information ("iSS") #403

Closed
XVilka opened this issue Jan 20, 2021 · 16 comments · Fixed by #1074
Closed

Add file offset and memory alignment for the ELF segments information ("iSS") #403

XVilka opened this issue Jan 20, 2021 · 16 comments · Fixed by #1074

Comments

@XVilka
Copy link
Member

XVilka commented Jan 20, 2021

iSS/iSSj should contain more information about segments in case of ELF. Two most important missing parts are file offset and memory alignment:

[0x00407f1c]> iSS
[Segments]

nth paddr          size vaddr         vsize perm name
―――――――――――――――――――――――――――――――――――――――――――――――――――――
0   0x00000040    0x1f8 0x00400040    0x1f8 -r-x PHDR
1   0x00000238     0x1c 0x00400238     0x1c -r-- INTERP
2   0x00000000  0x31d8c 0x00400000  0x31d8c -r-x LOAD0
3   0x00031e08   0x13e8 0x00631e08   0x4c90 -rw- LOAD1
4   0x00031e18    0x1e0 0x00631e18    0x1e0 -rw- DYNAMIC
5   0x00000254     0x20 0x00400254     0x20 -r-- NOTE
6   0x0002cc68    0xacc 0x0042cc68    0xacc -r-- GNU_EH_FRAME
7   0x00000000      0x0 0x00000000      0x0 -rw- GNU_STACK
8   0x00031e08    0x1f8 0x00631e08    0x1f8 -r-- GNU_RELRO
9   0x00000000     0x40 0x00400000     0x40 -rw- ehdr

Compare that with the output of readelf -lW:

[i] ℤ readelf -lW 001.make.elf.x86_64                                                                                                                                                                                             16:10:08 

Elf file type is EXEC (Executable file)
Entry point 0x407f1c
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0x0000000000400040 0x0000000000400040 0x0001f8 0x0001f8 R E 0x8
  INTERP         0x000238 0x0000000000400238 0x0000000000400238 0x00001c 0x00001c R   0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x000000 0x0000000000400000 0x0000000000400000 0x031d8c 0x031d8c R E 0x200000
  LOAD           0x031e08 0x0000000000631e08 0x0000000000631e08 0x0013e8 0x004c90 RW  0x200000
  DYNAMIC        0x031e18 0x0000000000631e18 0x0000000000631e18 0x0001e0 0x0001e0 RW  0x8
  NOTE           0x000254 0x0000000000400254 0x0000000000400254 0x000020 0x000020 R   0x4
  GNU_EH_FRAME   0x02cc68 0x000000000042cc68 0x000000000042cc68 0x000acc 0x000acc R   0x4
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10
  GNU_RELRO      0x031e08 0x0000000000631e08 0x0000000000631e08 0x0001f8 0x0001f8 R   0x1

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 
   03     .init_array .fini_array .dynamic .got .got.plt .data .bss 
   04     .dynamic 
   05     .note.ABI-tag 
   06     .eh_frame_hdr 
   07     
   08     .init_array .fini_array .dynamic .got 

001.make.elf.x86_64.zip

@XVilka XVilka added this to the 0.2.0 milestone Jan 20, 2021
@XVilka XVilka modified the milestones: 0.2.0, 0.3.0 Mar 1, 2021
@XVilka XVilka added the RSoC label Mar 5, 2021
@HuangPayoung
Copy link

HuangPayoung commented Mar 7, 2021

I follow BUILDING.md and finish it. Now I use rizin to test iSS command, comparing with readelf.
File offset and memory alignment are in the same struct with virtual address, maybe I can follow the iSS code to fix it.
I read the document, but the project is big and I can't search iSS command in document.
@XVilka @fangxlmr Can you help me that which file is about iSS command source code?

@XVilka
Copy link
Member Author

XVilka commented Mar 7, 2021 via email

@HuangPayoung
Copy link

Thank you. I will view the source code and learn from it.

@XVilka
Copy link
Member Author

XVilka commented Mar 8, 2021

@HuangPayoung you could check also this work-in-progress pull request that does a similar thing but for the binary sections, not segments. Hope that helps. #746

@HuangPayoung
Copy link

HuangPayoung commented Mar 12, 2021

I change the output as follow :

[0x00407f1c]> iSS
[Segments]

nth paddr          size vaddr         vsize perm name         offset     align
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
0   0x00000040    0x1f8 0x00400040    0x1f8 -r-x PHDR         0x00001000 0x0
1   0x00000238     0x1c 0x00400238     0x1c -r-- INTERP       0x00001000 0x0
2   0x00000000  0x31d8c 0x00400000  0x31d8c -r-x LOAD0        0x00001000 0x0
3   0x00031e08   0x13e8 0x00631e08   0x4c90 -rw- LOAD1        0x00001000 0x0
4   0x00031e18    0x1e0 0x00631e18    0x1e0 -rw- DYNAMIC      0x00001000 0x0
5   0x00000254     0x20 0x00400254     0x20 -r-- NOTE         0x00001000 0x0
6   0x0002cc68    0xacc 0x0042cc68    0xacc -r-- GNU_EH_FRAME 0x00001000 0x0
7   0x00000000      0x0 0x00000000      0x0 -rw- GNU_STACK    0x00001000 0x0
8   0x00031e08    0x1f8 0x00631e08    0x1f8 -r-- GNU_RELRO    0x00001000 0x0
9   0x00000000     0x40 0x00400000     0x40 -rw- ehdr         0x00001000 0x0

I think the next step is to add ut64 offset; ut64 align; in this struct and read them from Program Header Table

typedef struct rz_bin_section_t {
	char *name;
	ut64 size;
	ut64 vsize;
	ut64 vaddr;
	ut64 paddr;
	ut32 perm;
	// per section platform info
	const char *arch;
	char *format;
	int bits;
	bool has_strings;
	bool add; // indicates when you want to add the section to io `S` command
	bool is_data;
	bool is_segment;
} RzBinSection;

I don't know how rz_bin_object_t::sections this list read from elf_file?
Can you give some advice? Thank you.
@XVilka @fangxlmr

@XVilka
Copy link
Member Author

XVilka commented Mar 15, 2021

@HuangPayoung
Copy link

Today is deadline the of RSoC.
I send a PullRequest #833 to report the work I have finish.
I haven't finished this issue, it still need to improve. Thank you.
@XVilka @fangxlmr

@Maijin Maijin mentioned this issue Mar 16, 2021
4 tasks
@HuangPayoung HuangPayoung mentioned this issue Mar 17, 2021
4 tasks
@rizinorg rizinorg deleted a comment from fangxlmr Mar 17, 2021
@ret2libc
Copy link
Member

iSS/iSSj should contain more information about segments in case of ELF. Two most important missing parts are file offset and memory alignmen

@XVilka I think the offset field is already present, but it's just called paddr in the output. No?

@fangxlmr
Copy link
Contributor

@chinggg This issue is asigned to you as RSoC micro-task, so you could work on this from now on. Feel free to ask questions and send Pull Requests.

In case for anyone who is not aware about RSoC.

CC @XVilka

@XVilka
Copy link
Member Author

XVilka commented Apr 23, 2021

@ret2libc those are a bit different, see #889

@chinggg
Copy link
Contributor

chinggg commented Apr 23, 2021

@XVilka Since the paddr is now actually the offset, I can try to add the memory alignment first.

@XVilka
Copy link
Member Author

XVilka commented Apr 23, 2021

@chinggg yes, go for it.

@chinggg
Copy link
Contributor

chinggg commented Apr 23, 2021

Now I just made the similar challenges as #845 do

--- a/librz/bin/p/bin_elf.inc
+++ b/librz/bin/p/bin_elf.inc
@@ -334,2 +334,3 @@ static RzList *sections(RzBinFile *bf) {
                        ptr->vaddr = section[i].rva;
+                       ptr->align = section[i].align;
                        ptr->type = section[i].type;
diff --git a/librz/core/cbin.c b/librz/core/cbin.c
index a32bbfc04..7c164a219 100644
--- a/librz/core/cbin.c
+++ b/librz/core/cbin.c
@@ -2918,2 +2918,5 @@ static int bin_sections(RzCore *r, PJ *pj, int mode, ut64 laddr, int va, ut64 at
                }
+               if (print_segments) {
+                       rz_table_set_columnsf(table, "x", "align");
+               }
                rz_table_align(table, 2, RZ_TABLE_ALIGN_RIGHT);
@@ -3028,2 +3031,5 @@ static int bin_sections(RzCore *r, PJ *pj, int mode, ut64 laddr, int va, ut64 at
                        }
+                       if (print_segments) {
+                               pj_kN(pj, "align", section->align);
+                       }
                        pj_kN(pj, "paddr", section->paddr);
@@ -3088,2 +3094,6 @@ static int bin_sections(RzCore *r, PJ *pj, int mode, ut64 laddr, int va, ut64 at
 
+                       if (print_segments) {
+                               rz_list_append(row_list, rz_str_newf("0x%" PFMT64x, section->align));
+                       }
+
                        rz_table_add_row_list(table, row_list);
diff --git a/librz/include/rz_bin.h b/librz/include/rz_bin.h
index 0db4af465..ff23c4bd2 100644
--- a/librz/include/rz_bin.h
+++ b/librz/include/rz_bin.h
@@ -577,2 +577,3 @@ typedef struct rz_bin_section_t {
        ut32 perm;
+       ut64 align;

But the align output is 0x0. It seems that align has not been read yet.

https://github.com/rizinorg/rizin/blob/dev/librz/bin/format/elf/elf.c#L3258-L3277

And I found the function RzBinElfSection *Elf_(rz_bin_elf_get_sections)(ELFOBJ *bin) in elf.c, which can be seen in the link above. There are statements like ret[i].align = bin->shdr[i].sh_addralign; in this function, but why does it not work? Does it have anything to do with these lines which return another function get_sections_from_phdr(bin)?

if (!bin->shdr) {
		//we don't give up search in phdr section
		return get_sections_from_phdr(bin);
	}

@XVilka Do I understand the functions correctly? Or I need to write code manually to read or caculate the alignment? Since you have told another one to see functions near static Elf_(Phdr) * get_dynamic_segment(ELFOBJ *bin). Thanks!

@XVilka
Copy link
Member Author

XVilka commented Apr 23, 2021

@chinggg because segments are specific to ELF and a couple other formats Rizin reuses RzBinSection datatype for both, but sets bool segment in case for segment. The code you saw align in doesn't execute in case of segments.

@XVilka
Copy link
Member Author

XVilka commented Apr 23, 2021

@chinggg please also be cautious about changing how phdr/shdr are read because of this quirk: librz/bin/format/elf/elf.c:318:

	/* Here is the where all the fun starts.
	 * Linux kernel since 2005 calculates phdr offset wrongly
	 * adding it to the load address (va of the LOAD0).
	 * See `fs/binfmt_elf.c` file this line:
	 *    NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff);
	 * So after the first read, we fix the address and read it again
	 */
	if (linux_kernel_hack && phdr_found) {
		ut64 load_addr = Elf_(rz_bin_elf_get_baddr)(bin);
		bin->ehdr.e_phoff = Elf_(rz_bin_elf_v2p)(bin, load_addr + bin->ehdr.e_phoff);
		return read_phdr(bin, false);
	}

@ret2libc
Copy link
Member

@ret2libc those are a bit different, see #889

Yes, I extracted some parts of the ELF spec in #889 (review) . However, I'm not sure we should really care about the physical address, as that is not used by applications and it would hardly be a concept that can be easily abstracted in RzBinSection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants