6 #include <sys/exec_elf.h>
8 /* Include ELF headers */
9 #include <sys/elf_core.h>
10 #include <machine/elf.h>
12 static void fill_elf_header(Elf32_Ehdr
*elf_header
, int phnum
);
13 static void fill_prog_header(Elf32_Phdr
*prog_header
, Elf32_Word
14 p_type
, Elf32_Off p_offset
, Elf32_Addr p_vaddr
, Elf32_Word p_flags
,
15 Elf32_Word p_filesz
, Elf32_Word p_memsz
);
16 static int get_memory_regions(Elf32_Phdr phdrs
[]);
17 static void fill_note_segment_and_entries_hdrs(Elf32_Phdr phdrs
[],
19 static void adjust_offsets(Elf32_Phdr phdrs
[], int phnum
);
20 static void dump_elf_header(struct filp
*f
, Elf32_Ehdr elf_header
);
21 static void dump_notes(struct filp
*f
, Elf32_Nhdr nhdrs
[], int csig
,
23 static void dump_program_headers(struct filp
*f
, Elf_Phdr phdrs
[], int
25 static void dump_segments(struct filp
*f
, Elf32_Phdr phdrs
[], int
27 static void write_buf(struct filp
*f
, char *buf
, size_t size
);
29 /*===========================================================================*
30 * write_elf_core_file *
31 *===========================================================================*/
32 void write_elf_core_file(struct filp
*f
, int csig
, char *proc_name
)
34 /* First, fill in all the required headers, second, adjust the offsets,
35 * third, dump everything into the core file
37 #define MAX_REGIONS 100
38 #define NR_NOTE_ENTRIES 2
40 Elf_Phdr phdrs
[MAX_REGIONS
+ 1];
41 Elf_Nhdr nhdrs
[NR_NOTE_ENTRIES
];
44 memset(phdrs
, 0, sizeof(phdrs
));
46 /* Fill in the NOTE Program Header - at phdrs[0] - and
47 * note entries' headers
49 fill_note_segment_and_entries_hdrs(phdrs
, nhdrs
);
51 /* Get the memory segments and fill in the Program headers */
52 phnum
= get_memory_regions(phdrs
) + 1;
54 /* Fill in the ELF header */
55 fill_elf_header(&elf_header
, phnum
);
57 /* Adjust offsets in program headers - The layout in the ELF core file
58 * is the following: the ELF Header, the Note Program Header,
59 * the rest of Program Headers (memory segments), Note contents,
60 * the program segments' contents
62 adjust_offsets(phdrs
, phnum
);
64 /* Write ELF header */
65 dump_elf_header(f
, elf_header
);
67 /* Write Program headers (Including the NOTE) */
68 dump_program_headers(f
, phdrs
, phnum
);
70 /* Write NOTE contents */
71 dump_notes(f
, nhdrs
, csig
, proc_name
);
73 /* Write segments' contents */
74 dump_segments(f
, phdrs
, phnum
);
77 /*===========================================================================*
79 *===========================================================================*/
80 static void fill_elf_header (Elf_Ehdr
*elf_header
, int phnum
)
82 memset((void *) elf_header
, 0, sizeof(Elf_Ehdr
));
84 elf_header
->e_ident
[EI_MAG0
] = ELFMAG0
;
85 elf_header
->e_ident
[EI_MAG1
] = ELFMAG1
;
86 elf_header
->e_ident
[EI_MAG2
] = ELFMAG2
;
87 elf_header
->e_ident
[EI_MAG3
] = ELFMAG3
;
88 elf_header
->e_ident
[EI_CLASS
] = ELF_TARG_CLASS
;
89 elf_header
->e_ident
[EI_DATA
] = ELF_TARG_DATA
;
90 elf_header
->e_ident
[EI_VERSION
] = EV_CURRENT
;
91 elf_header
->e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
92 elf_header
->e_type
= ET_CORE
;
93 elf_header
->e_machine
= ELF_TARG_MACH
;
94 elf_header
->e_version
= EV_CURRENT
;
95 elf_header
->e_ehsize
= sizeof(Elf_Ehdr
);
96 elf_header
->e_phoff
= sizeof(Elf_Ehdr
);
97 elf_header
->e_phentsize
= sizeof(Elf_Phdr
);
98 elf_header
->e_phnum
= phnum
;
101 /*===========================================================================*
103 *===========================================================================*/
104 static void fill_prog_header (Elf_Phdr
*prog_header
, Elf_Word p_type
,
105 Elf_Off p_offset
, Elf_Addr p_vaddr
, Elf_Word p_flags
,
106 Elf_Word p_filesz
, Elf_Word p_memsz
)
109 memset((void *) prog_header
, 0, sizeof(Elf_Phdr
));
111 prog_header
->p_type
= p_type
;
112 prog_header
->p_offset
= p_offset
;
113 prog_header
->p_vaddr
= p_vaddr
;
114 prog_header
->p_flags
= p_flags
;
115 prog_header
->p_filesz
= p_filesz
;
116 prog_header
->p_memsz
= p_memsz
;
121 #define PAD_LEN(x) ((x + (PADBYTES - 1)) & ~(PADBYTES - 1))
123 /*===========================================================================*
124 * fill_note_segment_and_entries_hdrs *
125 *===========================================================================*/
126 static void fill_note_segment_and_entries_hdrs(Elf_Phdr phdrs
[],
130 const char *note_name
= ELF_NOTE_MINIX_ELFCORE_NAME
"\0";
131 int name_len
, mei_len
, gregs_len
;
133 /* Size of notes in the core file is rather fixed:
134 * sizeof(minix_elfcore_info_t) +
135 * 2 * sizeof(Elf_Nhdr) + the size of the padded name of the note
136 * - i.e. "MINIX-CORE\0" padded to 4-byte alignment => 2 * 8 bytes
139 name_len
= strlen(note_name
) + 1;
140 mei_len
= sizeof(minix_elfcore_info_t
);
141 gregs_len
= sizeof(gregset_t
);
143 /* Make sure to also count the padding bytes */
144 filesize
= PAD_LEN(mei_len
) + PAD_LEN(gregs_len
) +
145 2 * sizeof(Elf_Nhdr
) + 2 * PAD_LEN(name_len
);
146 fill_prog_header(&phdrs
[0], PT_NOTE
, 0, 0, PF_R
, filesize
, 0);
148 /* First note entry header */
149 nhdrs
[0].n_namesz
= name_len
;
150 nhdrs
[0].n_descsz
= sizeof(minix_elfcore_info_t
);
151 nhdrs
[0].n_type
= NT_MINIX_ELFCORE_INFO
;
153 /* Second note entry header */
154 nhdrs
[1].n_namesz
= name_len
;
155 nhdrs
[1].n_descsz
= sizeof(gregset_t
);
156 nhdrs
[1].n_type
= NT_MINIX_ELFCORE_GREGS
;
159 /*===========================================================================*
161 *===========================================================================*/
162 static void adjust_offsets(Elf_Phdr phdrs
[], int phnum
)
165 long offset
= sizeof(Elf_Ehdr
) + phnum
* sizeof(Elf_Phdr
);
167 for (i
= 0; i
< phnum
; i
++) {
168 phdrs
[i
].p_offset
= offset
;
169 offset
+= phdrs
[i
].p_filesz
;
173 /*===========================================================================*
175 *===========================================================================*/
176 static void write_buf(struct filp
*f
, char *buf
, size_t size
)
178 read_write(fp
, WRITING
, f
, (vir_bytes
)buf
, size
, VFS_PROC_NR
);
181 /*===========================================================================*
182 * get_memory_regions *
183 *===========================================================================*/
184 static int get_memory_regions(Elf_Phdr phdrs
[])
186 /* Print the virtual memory regions of a process. */
188 /* The same as dump_regions from procfs/pid.c */
189 struct vm_region_info vri
[MAX_VRI_COUNT
];
198 r
= vm_info_region(fp
->fp_endpoint
, vri
, MAX_VRI_COUNT
, &next
);
202 for (i
= 0; i
< r
; i
++) {
203 pflags
= (vri
[i
].vri_prot
& PROT_READ
? PF_R
: 0)
204 | (vri
[i
].vri_prot
& PROT_WRITE
? PF_W
: 0)
205 | (vri
[i
].vri_prot
& PROT_EXEC
? PF_X
: 0);
207 fill_prog_header (&phdrs
[count
+ 1], PT_LOAD
,
208 0, vri
[i
].vri_addr
, pflags
,
209 vri
[i
].vri_length
, vri
[i
].vri_length
);
212 if (count
>= MAX_REGIONS
) {
213 printf("VFS: get_memory_regions Warning: "
214 "Program has too many regions\n");
218 } while (r
== MAX_VRI_COUNT
);
223 /*===========================================================================*
225 *===========================================================================*/
226 static void dump_notes(struct filp
*f
, Elf_Nhdr nhdrs
[], int csig
,
229 char *note_name
= ELF_NOTE_MINIX_ELFCORE_NAME
"\0";
231 minix_elfcore_info_t mei
;
232 int mei_len
= sizeof(minix_elfcore_info_t
);
233 int gregs_len
= sizeof(gregset_t
);
234 struct stackframe_s regs
;
236 /* Dump first note entry */
237 mei
.mei_version
= MINIX_ELFCORE_VERSION
;
238 mei
.mei_meisize
= mei_len
;
239 mei
.mei_signo
= csig
;
240 mei
.mei_pid
= fp
->fp_pid
;
241 memcpy(mei
.mei_command
, proc_name
, sizeof(mei
.mei_command
));
243 write_buf(f
, (char *) &nhdrs
[0], sizeof(Elf_Nhdr
));
244 write_buf(f
, note_name
, nhdrs
[0].n_namesz
);
245 write_buf(f
, pad
, PAD_LEN(nhdrs
[0].n_namesz
) - nhdrs
[0].n_namesz
);
246 write_buf(f
, (char *) &mei
, mei_len
);
247 write_buf(f
, pad
, PAD_LEN(mei_len
) - mei_len
);
250 if (sys_getregs(®s
, fp
->fp_endpoint
) != OK
)
251 printf("VFS: Could not read registers\n");
253 if (sizeof(regs
) != gregs_len
)
254 printf("VFS: Wrong core register structure size\n");
256 /* Dump second note entry - the general registers */
257 write_buf(f
, (char *) &nhdrs
[1], sizeof(Elf_Nhdr
));
259 write_buf(f
, note_name
, nhdrs
[1].n_namesz
);
260 write_buf(f
, pad
, PAD_LEN(nhdrs
[1].n_namesz
) - nhdrs
[1].n_namesz
);
261 write_buf(f
, (char *) ®s
, gregs_len
);
262 write_buf(f
, pad
, PAD_LEN(gregs_len
) - gregs_len
);
265 /*===========================================================================*
267 *===========================================================================*/
268 static void dump_elf_header(struct filp
*f
, Elf_Ehdr elf_header
)
270 write_buf(f
, (char *) &elf_header
, sizeof(Elf_Ehdr
));
273 /*===========================================================================*
274 * dump_program_headers *
275 *===========================================================================*/
276 static void dump_program_headers(struct filp
*f
, Elf_Phdr phdrs
[], int phnum
)
280 for (i
= 0; i
< phnum
; i
++)
281 write_buf(f
, (char *) &phdrs
[i
], sizeof(Elf_Phdr
));
284 /*===========================================================================*
286 *===========================================================================*/
287 static void dump_segments(struct filp
*f
, Elf_Phdr phdrs
[], int phnum
)
293 static u8_t buf
[CLICK_SIZE
];
295 for (i
= 1; i
< phnum
; i
++) {
296 len
= phdrs
[i
].p_memsz
;
297 seg_off
= phdrs
[i
].p_vaddr
;
299 if (len
> LONG_MAX
) {
300 printf("VFS: segment too large to dump, truncating\n");
304 for (off
= 0; off
< (off_t
) len
; off
+= CLICK_SIZE
) {
305 vir_bytes p
= (vir_bytes
) (seg_off
+ off
);
306 r
= sys_datacopy_try(fp
->fp_endpoint
, p
,
307 SELF
, (vir_bytes
) buf
,
308 (phys_bytes
) CLICK_SIZE
);
311 /* memory didn't exist; write as zeroes */
312 memset(buf
, 0, sizeof(buf
));
316 write_buf(f
, (char *) buf
, (off
+ CLICK_SIZE
<= (off_t
) len
) ?
317 CLICK_SIZE
: (len
- off
));