7 #include <sys/exec_elf.h>
10 /* Include ELF headers */
11 #include <sys/elf_core.h>
12 #include <machine/elf.h>
14 static void fill_elf_header(Elf32_Ehdr
*elf_header
, int phnum
);
15 static void fill_prog_header(Elf32_Phdr
*prog_header
, Elf32_Word
16 p_type
, Elf32_Off p_offset
, Elf32_Addr p_vaddr
, Elf32_Word p_flags
,
17 Elf32_Word p_filesz
, Elf32_Word p_memsz
);
18 static int get_memory_regions(Elf32_Phdr phdrs
[]);
19 static void fill_note_segment_and_entries_hdrs(Elf32_Phdr phdrs
[],
21 static void adjust_offsets(Elf32_Phdr phdrs
[], int phnum
);
22 static void dump_elf_header(struct filp
*f
, Elf32_Ehdr elf_header
);
23 static void dump_notes(struct filp
*f
, Elf32_Nhdr nhdrs
[], int csig
,
25 static void dump_program_headers(struct filp
*f
, Elf_Phdr phdrs
[], int
27 static void dump_segments(struct filp
*f
, Elf32_Phdr phdrs
[], int
29 static void write_buf(struct filp
*f
, char *buf
, size_t size
);
31 /*===========================================================================*
32 * write_elf_core_file *
33 *===========================================================================*/
34 void write_elf_core_file(struct filp
*f
, int csig
, char *proc_name
)
36 /* First, fill in all the required headers, second, adjust the offsets,
37 * third, dump everything into the core file
39 #define MAX_REGIONS 100
40 #define NR_NOTE_ENTRIES 2
42 Elf_Phdr phdrs
[MAX_REGIONS
+ 1];
43 Elf_Nhdr nhdrs
[NR_NOTE_ENTRIES
];
46 memset(phdrs
, 0, sizeof(phdrs
));
48 /* Fill in the NOTE Program Header - at phdrs[0] - and
49 * note entries' headers
51 fill_note_segment_and_entries_hdrs(phdrs
, nhdrs
);
53 /* Get the memory segments and fill in the Program headers */
54 phnum
= get_memory_regions(phdrs
) + 1;
56 /* Fill in the ELF header */
57 fill_elf_header(&elf_header
, phnum
);
59 /* Adjust offsets in program headers - The layout in the ELF core file
60 * is the following: the ELF Header, the Note Program Header,
61 * the rest of Program Headers (memory segments), Note contents,
62 * the program segments' contents
64 adjust_offsets(phdrs
, phnum
);
66 /* Write ELF header */
67 dump_elf_header(f
, elf_header
);
69 /* Write Program headers (Including the NOTE) */
70 dump_program_headers(f
, phdrs
, phnum
);
72 /* Write NOTE contents */
73 dump_notes(f
, nhdrs
, csig
, proc_name
);
75 /* Write segments' contents */
76 dump_segments(f
, phdrs
, phnum
);
79 /*===========================================================================*
81 *===========================================================================*/
82 static void fill_elf_header (Elf_Ehdr
*elf_header
, int phnum
)
84 memset((void *) elf_header
, 0, sizeof(Elf_Ehdr
));
86 elf_header
->e_ident
[EI_MAG0
] = ELFMAG0
;
87 elf_header
->e_ident
[EI_MAG1
] = ELFMAG1
;
88 elf_header
->e_ident
[EI_MAG2
] = ELFMAG2
;
89 elf_header
->e_ident
[EI_MAG3
] = ELFMAG3
;
90 elf_header
->e_ident
[EI_CLASS
] = ELF_TARG_CLASS
;
91 elf_header
->e_ident
[EI_DATA
] = ELF_TARG_DATA
;
92 elf_header
->e_ident
[EI_VERSION
] = EV_CURRENT
;
93 elf_header
->e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
94 elf_header
->e_type
= ET_CORE
;
95 elf_header
->e_machine
= ELF_TARG_MACH
;
96 elf_header
->e_version
= EV_CURRENT
;
97 elf_header
->e_ehsize
= sizeof(Elf_Ehdr
);
98 elf_header
->e_phoff
= sizeof(Elf_Ehdr
);
99 elf_header
->e_phentsize
= sizeof(Elf_Phdr
);
100 elf_header
->e_phnum
= phnum
;
103 /*===========================================================================*
105 *===========================================================================*/
106 static void fill_prog_header (Elf_Phdr
*prog_header
, Elf_Word p_type
,
107 Elf_Off p_offset
, Elf_Addr p_vaddr
, Elf_Word p_flags
,
108 Elf_Word p_filesz
, Elf_Word p_memsz
)
111 memset((void *) prog_header
, 0, sizeof(Elf_Phdr
));
113 prog_header
->p_type
= p_type
;
114 prog_header
->p_offset
= p_offset
;
115 prog_header
->p_vaddr
= p_vaddr
;
116 prog_header
->p_flags
= p_flags
;
117 prog_header
->p_filesz
= p_filesz
;
118 prog_header
->p_memsz
= p_memsz
;
123 #define PAD_LEN(x) ((x + (PADBYTES - 1)) & ~(PADBYTES - 1))
125 /*===========================================================================*
126 * fill_note_segment_and_entries_hdrs *
127 *===========================================================================*/
128 static void fill_note_segment_and_entries_hdrs(Elf_Phdr phdrs
[],
132 const char *note_name
= ELF_NOTE_MINIX_ELFCORE_NAME
"\0";
133 int name_len
, mei_len
, gregs_len
;
135 /* Size of notes in the core file is rather fixed:
136 * sizeof(minix_elfcore_info_t) +
137 * 2 * sizeof(Elf_Nhdr) + the size of the padded name of the note
138 * - i.e. "MINIX-CORE\0" padded to 4-byte alignment => 2 * 8 bytes
141 name_len
= strlen(note_name
) + 1;
142 mei_len
= sizeof(minix_elfcore_info_t
);
143 gregs_len
= sizeof(gregset_t
);
145 /* Make sure to also count the padding bytes */
146 filesize
= PAD_LEN(mei_len
) + PAD_LEN(gregs_len
) +
147 2 * sizeof(Elf_Nhdr
) + 2 * PAD_LEN(name_len
);
148 fill_prog_header(&phdrs
[0], PT_NOTE
, 0, 0, PF_R
, filesize
, 0);
150 /* First note entry header */
151 nhdrs
[0].n_namesz
= name_len
;
152 nhdrs
[0].n_descsz
= sizeof(minix_elfcore_info_t
);
153 nhdrs
[0].n_type
= NT_MINIX_ELFCORE_INFO
;
155 /* Second note entry header */
156 nhdrs
[1].n_namesz
= name_len
;
157 nhdrs
[1].n_descsz
= sizeof(gregset_t
);
158 nhdrs
[1].n_type
= NT_MINIX_ELFCORE_GREGS
;
161 /*===========================================================================*
163 *===========================================================================*/
164 static void adjust_offsets(Elf_Phdr phdrs
[], int phnum
)
167 long offset
= sizeof(Elf_Ehdr
) + phnum
* sizeof(Elf_Phdr
);
169 for (i
= 0; i
< phnum
; i
++) {
170 phdrs
[i
].p_offset
= offset
;
171 offset
+= phdrs
[i
].p_filesz
;
175 /*===========================================================================*
177 *===========================================================================*/
178 static void write_buf(struct filp
*f
, char *buf
, size_t size
)
180 read_write(WRITING
, f
, buf
, size
, VFS_PROC_NR
);
183 /*===========================================================================*
184 * get_memory_regions *
185 *===========================================================================*/
186 static int get_memory_regions(Elf_Phdr phdrs
[])
188 /* Print the virtual memory regions of a process. */
190 /* The same as dump_regions from procfs/pid.c */
191 struct vm_region_info vri
[MAX_VRI_COUNT
];
200 r
= vm_info_region(fp
->fp_endpoint
, vri
, MAX_VRI_COUNT
, &next
);
204 for (i
= 0; i
< r
; i
++) {
205 pflags
= (vri
[i
].vri_prot
& PROT_READ
? PF_R
: 0)
206 | (vri
[i
].vri_prot
& PROT_WRITE
? PF_W
: 0)
207 | (vri
[i
].vri_prot
& PROT_EXEC
? PF_X
: 0);
209 fill_prog_header (&phdrs
[count
+ 1], PT_LOAD
,
210 0, vri
[i
].vri_addr
, pflags
,
211 vri
[i
].vri_length
, vri
[i
].vri_length
);
214 if (count
>= MAX_REGIONS
) {
215 printf("VFS: get_memory_regions Warning: "
216 "Program has too many regions\n");
220 } while (r
== MAX_VRI_COUNT
);
225 /*===========================================================================*
227 *===========================================================================*/
228 static void dump_notes(struct filp
*f
, Elf_Nhdr nhdrs
[], int csig
,
231 char *note_name
= ELF_NOTE_MINIX_ELFCORE_NAME
"\0";
233 minix_elfcore_info_t mei
;
234 int mei_len
= sizeof(minix_elfcore_info_t
);
235 int gregs_len
= sizeof(gregset_t
);
236 struct stackframe_s regs
;
238 /* Dump first note entry */
239 mei
.mei_version
= MINIX_ELFCORE_VERSION
;
240 mei
.mei_meisize
= mei_len
;
241 mei
.mei_signo
= csig
;
242 mei
.mei_pid
= fp
->fp_pid
;
243 memcpy(mei
.mei_command
, proc_name
, sizeof(mei
.mei_command
));
245 write_buf(f
, (char *) &nhdrs
[0], sizeof(Elf_Nhdr
));
246 write_buf(f
, note_name
, nhdrs
[0].n_namesz
);
247 write_buf(f
, pad
, PAD_LEN(nhdrs
[0].n_namesz
) - nhdrs
[0].n_namesz
);
248 write_buf(f
, (char *) &mei
, mei_len
);
249 write_buf(f
, pad
, PAD_LEN(mei_len
) - mei_len
);
252 if (sys_getregs(®s
, fp
->fp_endpoint
) != OK
)
253 printf("VFS: Could not read registers\n");
255 if (sizeof(regs
) != gregs_len
)
256 printf("VFS: Wrong core register structure size\n");
258 /* Dump second note entry - the general registers */
259 write_buf(f
, (char *) &nhdrs
[1], sizeof(Elf_Nhdr
));
261 write_buf(f
, note_name
, nhdrs
[1].n_namesz
);
262 write_buf(f
, pad
, PAD_LEN(nhdrs
[1].n_namesz
) - nhdrs
[1].n_namesz
);
263 write_buf(f
, (char *) ®s
, gregs_len
);
264 write_buf(f
, pad
, PAD_LEN(gregs_len
) - gregs_len
);
267 /*===========================================================================*
269 *===========================================================================*/
270 static void dump_elf_header(struct filp
*f
, Elf_Ehdr elf_header
)
272 write_buf(f
, (char *) &elf_header
, sizeof(Elf_Ehdr
));
275 /*===========================================================================*
276 * dump_program_headers *
277 *===========================================================================*/
278 static void dump_program_headers(struct filp
*f
, Elf_Phdr phdrs
[], int phnum
)
282 for (i
= 0; i
< phnum
; i
++)
283 write_buf(f
, (char *) &phdrs
[i
], sizeof(Elf_Phdr
));
286 /*===========================================================================*
288 *===========================================================================*/
289 static void dump_segments(struct filp
*f
, Elf_Phdr phdrs
[], int phnum
)
295 static u8_t buf
[CLICK_SIZE
];
297 for (i
= 1; i
< phnum
; i
++) {
298 len
= phdrs
[i
].p_memsz
;
299 seg_off
= phdrs
[i
].p_vaddr
;
301 if (len
> LONG_MAX
) {
302 printf("VFS: segment too large to dump, truncating\n");
306 for (off
= 0; off
< (off_t
) len
; off
+= CLICK_SIZE
) {
307 vir_bytes p
= (vir_bytes
) (seg_off
+ off
);
308 r
= sys_vircopy(fp
->fp_endpoint
, p
,
309 SELF
, (vir_bytes
) buf
,
310 (phys_bytes
) CLICK_SIZE
);
313 printf("VFS: vircopy failed for %d @ 0x%lx during coredump\n",
318 write_buf(f
, (char *) buf
, (off
+ CLICK_SIZE
<= (off_t
) len
) ?
319 CLICK_SIZE
: (len
- off
));