 24ec0d73b5
			
		
	
	
		24ec0d73b5
		
	
	
	
	
		
			
			- introduce new call numbers, names, and field aliases; - initialize request messages to zero for all ABI calls; - format callnr.h in the same way as com.h; - redo call tables in both servers; - remove param.h namespace pollution in the servers; - make brk(2) go to VM directly, rather than through PM; - remove obsolete BRK, UTIME, and WAIT calls; - clean up path copying routine in VFS; - move remaining system calls from libminlib to libc; - correct some errno-related mistakes in libc routines. Change-Id: I2d8ec5d061cd7e0b30c51ffd77aa72ebf84e2565
		
			
				
	
	
		
			321 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			321 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "fs.h"
 | |
| #include <fcntl.h>
 | |
| #include <string.h>
 | |
| #include <minix/vm.h>
 | |
| #include <sys/mman.h>
 | |
| #include <sys/exec_elf.h>
 | |
| 
 | |
| /* Include ELF headers */
 | |
| #include <sys/elf_core.h>
 | |
| #include <machine/elf.h>
 | |
| 
 | |
| static void fill_elf_header(Elf32_Ehdr *elf_header, int phnum);
 | |
| static void fill_prog_header(Elf32_Phdr *prog_header, Elf32_Word
 | |
| 	p_type, Elf32_Off p_offset, Elf32_Addr p_vaddr, Elf32_Word p_flags,
 | |
| 	Elf32_Word p_filesz, Elf32_Word p_memsz);
 | |
| static int get_memory_regions(Elf32_Phdr phdrs[]);
 | |
| static void fill_note_segment_and_entries_hdrs(Elf32_Phdr phdrs[],
 | |
| 	Elf32_Nhdr nhdrs[]);
 | |
| static void adjust_offsets(Elf32_Phdr phdrs[], int phnum);
 | |
| static void dump_elf_header(struct filp *f, Elf32_Ehdr elf_header);
 | |
| static void dump_notes(struct filp *f, Elf32_Nhdr nhdrs[], int csig,
 | |
| 	char *proc_name);
 | |
| static void dump_program_headers(struct filp *f, Elf_Phdr phdrs[], int
 | |
| 	phnum);
 | |
| static void dump_segments(struct filp *f, Elf32_Phdr phdrs[], int
 | |
| 	phnum);
 | |
| static void write_buf(struct filp *f, char *buf, size_t size);
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				write_elf_core_file			     *
 | |
|  *===========================================================================*/
 | |
| void write_elf_core_file(struct filp *f, int csig, char *proc_name)
 | |
| {
 | |
| /* First, fill in all the required headers, second, adjust the offsets,
 | |
|  * third, dump everything into the core file
 | |
|  */
 | |
| #define MAX_REGIONS 100
 | |
| #define NR_NOTE_ENTRIES 2
 | |
|   Elf_Ehdr elf_header;
 | |
|   Elf_Phdr phdrs[MAX_REGIONS + 1];
 | |
|   Elf_Nhdr nhdrs[NR_NOTE_ENTRIES];
 | |
|   int phnum;
 | |
| 
 | |
|   memset(phdrs, 0, sizeof(phdrs));
 | |
| 
 | |
|   /* Fill in the NOTE Program Header - at phdrs[0] - and
 | |
|    * note entries' headers
 | |
|    */
 | |
|   fill_note_segment_and_entries_hdrs(phdrs, nhdrs);
 | |
| 
 | |
|   /* Get the memory segments and fill in the Program headers */
 | |
|   phnum = get_memory_regions(phdrs) + 1;
 | |
| 
 | |
|   /* Fill in the ELF header */
 | |
|   fill_elf_header(&elf_header, phnum);
 | |
| 
 | |
|   /* Adjust offsets in program headers - The layout in the ELF core file
 | |
|    * is the following: the ELF Header, the Note Program Header,
 | |
|    * the rest of Program Headers (memory segments), Note contents,
 | |
|    * the program segments' contents
 | |
|    */
 | |
|   adjust_offsets(phdrs, phnum);
 | |
| 
 | |
|   /* Write ELF header */
 | |
|   dump_elf_header(f, elf_header);
 | |
| 
 | |
|   /* Write Program headers (Including the NOTE) */
 | |
|   dump_program_headers(f, phdrs, phnum);
 | |
| 
 | |
|   /* Write NOTE contents */
 | |
|   dump_notes(f, nhdrs, csig, proc_name);
 | |
| 
 | |
|   /* Write segments' contents */
 | |
|   dump_segments(f, phdrs, phnum);
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				fill_elf_header        			     *
 | |
|  *===========================================================================*/
 | |
| static void fill_elf_header (Elf_Ehdr *elf_header, int phnum)
 | |
| {
 | |
|   memset((void *) elf_header, 0, sizeof(Elf_Ehdr));
 | |
| 
 | |
|   elf_header->e_ident[EI_MAG0] = ELFMAG0;
 | |
|   elf_header->e_ident[EI_MAG1] = ELFMAG1;
 | |
|   elf_header->e_ident[EI_MAG2] = ELFMAG2;
 | |
|   elf_header->e_ident[EI_MAG3] = ELFMAG3;
 | |
|   elf_header->e_ident[EI_CLASS] = ELF_TARG_CLASS;
 | |
|   elf_header->e_ident[EI_DATA] = ELF_TARG_DATA;
 | |
|   elf_header->e_ident[EI_VERSION] = EV_CURRENT;
 | |
|   elf_header->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
 | |
|   elf_header->e_type = ET_CORE;
 | |
|   elf_header->e_machine = ELF_TARG_MACH;
 | |
|   elf_header->e_version = EV_CURRENT;
 | |
|   elf_header->e_ehsize = sizeof(Elf_Ehdr);
 | |
|   elf_header->e_phoff = sizeof(Elf_Ehdr);
 | |
|   elf_header->e_phentsize = sizeof(Elf_Phdr);
 | |
|   elf_header->e_phnum = phnum;
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				fill_prog_header        		     *
 | |
|  *===========================================================================*/
 | |
| static void fill_prog_header (Elf_Phdr *prog_header, Elf_Word p_type,
 | |
| 	Elf_Off p_offset, Elf_Addr p_vaddr, Elf_Word p_flags,
 | |
| 	Elf_Word p_filesz, Elf_Word p_memsz)
 | |
| {
 | |
| 
 | |
|   memset((void *) prog_header, 0, sizeof(Elf_Phdr));
 | |
| 
 | |
|   prog_header->p_type = p_type;
 | |
|   prog_header->p_offset = p_offset;
 | |
|   prog_header->p_vaddr = p_vaddr;
 | |
|   prog_header->p_flags = p_flags;
 | |
|   prog_header->p_filesz = p_filesz;
 | |
|   prog_header->p_memsz = p_memsz;
 | |
| 
 | |
| }
 | |
| 
 | |
| #define PADBYTES    4
 | |
| #define PAD_LEN(x)  ((x + (PADBYTES - 1)) & ~(PADBYTES - 1))
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *			fill_note_segment_and_entries_hdrs     	     	     *
 | |
|  *===========================================================================*/
 | |
| static void fill_note_segment_and_entries_hdrs(Elf_Phdr phdrs[],
 | |
| 				Elf_Nhdr nhdrs[])
 | |
| {
 | |
|   int filesize;
 | |
|   const char *note_name = ELF_NOTE_MINIX_ELFCORE_NAME "\0";
 | |
|   int name_len, mei_len, gregs_len;
 | |
| 
 | |
|   /* Size of notes in the core file is rather fixed:
 | |
|    * sizeof(minix_elfcore_info_t) +
 | |
|    * 2 * sizeof(Elf_Nhdr) + the size of the padded name of the note
 | |
|    * - i.e. "MINIX-CORE\0" padded to 4-byte alignment => 2 * 8 bytes
 | |
|    */
 | |
| 
 | |
|   name_len = strlen(note_name) + 1;
 | |
|   mei_len = sizeof(minix_elfcore_info_t);
 | |
|   gregs_len = sizeof(gregset_t);
 | |
| 
 | |
|   /* Make sure to also count the padding bytes */
 | |
|   filesize = PAD_LEN(mei_len) + PAD_LEN(gregs_len) +
 | |
| 	2 * sizeof(Elf_Nhdr) + 2 * PAD_LEN(name_len);
 | |
|   fill_prog_header(&phdrs[0], PT_NOTE, 0, 0, PF_R, filesize, 0);
 | |
| 
 | |
|   /* First note entry header */
 | |
|   nhdrs[0].n_namesz = name_len;
 | |
|   nhdrs[0].n_descsz = sizeof(minix_elfcore_info_t);
 | |
|   nhdrs[0].n_type = NT_MINIX_ELFCORE_INFO;
 | |
| 
 | |
|   /* Second note entry header */
 | |
|   nhdrs[1].n_namesz = name_len;
 | |
|   nhdrs[1].n_descsz = sizeof(gregset_t);
 | |
|   nhdrs[1].n_type = NT_MINIX_ELFCORE_GREGS;
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				adjust_offset   			     *
 | |
|  *===========================================================================*/
 | |
| static void adjust_offsets(Elf_Phdr phdrs[], int phnum)
 | |
| {
 | |
|   int i;
 | |
|   long offset = sizeof(Elf_Ehdr) + phnum * sizeof(Elf_Phdr);
 | |
| 
 | |
|   for (i = 0; i < phnum; i++) {
 | |
| 	phdrs[i].p_offset = offset;
 | |
| 	offset += phdrs[i].p_filesz;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				write_buf       			     *
 | |
|  *===========================================================================*/
 | |
| static void write_buf(struct filp *f, char *buf, size_t size)
 | |
| {
 | |
|   read_write(fp, WRITING, f, buf, size, VFS_PROC_NR);
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				get_memory_regions			     *
 | |
|  *===========================================================================*/
 | |
| static int get_memory_regions(Elf_Phdr phdrs[])
 | |
| {
 | |
|   /* Print the virtual memory regions of a process. */
 | |
| 
 | |
|   /* The same as dump_regions from procfs/pid.c */
 | |
|   struct vm_region_info vri[MAX_VRI_COUNT];
 | |
|   vir_bytes next;
 | |
|   int i, r, count;
 | |
|   Elf_Word pflags;
 | |
| 
 | |
|   count = 0;
 | |
|   next = 0;
 | |
| 
 | |
|   do {
 | |
| 	r = vm_info_region(fp->fp_endpoint, vri, MAX_VRI_COUNT, &next);
 | |
| 	if (r < 0) return r;
 | |
| 	if (r == 0) break;
 | |
| 
 | |
| 	for (i = 0; i < r; i++) {
 | |
| 		pflags =  (vri[i].vri_prot & PROT_READ ? PF_R : 0)
 | |
| 			| (vri[i].vri_prot & PROT_WRITE ? PF_W : 0)
 | |
| 			| (vri[i].vri_prot & PROT_EXEC ? PF_X : 0);
 | |
| 
 | |
| 		fill_prog_header (&phdrs[count + 1], PT_LOAD,
 | |
| 				0, vri[i].vri_addr, pflags,
 | |
| 				vri[i].vri_length, vri[i].vri_length);
 | |
| 		count++;
 | |
| 
 | |
| 		if (count >= MAX_REGIONS) {
 | |
| 			printf("VFS: get_memory_regions Warning: "
 | |
| 				"Program has too many regions\n");
 | |
| 			return(count);
 | |
| 		}
 | |
| 	}
 | |
|   } while (r == MAX_VRI_COUNT);
 | |
| 
 | |
|   return(count);
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				dump_notes			             *
 | |
|  *===========================================================================*/
 | |
| static void dump_notes(struct filp *f, Elf_Nhdr nhdrs[], int csig,
 | |
| 			 char *proc_name)
 | |
| {
 | |
|   char *note_name = ELF_NOTE_MINIX_ELFCORE_NAME "\0";
 | |
|   char pad[4];
 | |
|   minix_elfcore_info_t mei;
 | |
|   int mei_len = sizeof(minix_elfcore_info_t);
 | |
|   int gregs_len = sizeof(gregset_t);
 | |
|   struct stackframe_s regs;
 | |
| 
 | |
|   /* Dump first note entry */
 | |
|   mei.mei_version = MINIX_ELFCORE_VERSION;
 | |
|   mei.mei_meisize = mei_len;
 | |
|   mei.mei_signo = csig;
 | |
|   mei.mei_pid = fp->fp_pid;
 | |
|   memcpy(mei.mei_command, proc_name, sizeof(mei.mei_command));
 | |
| 
 | |
|   write_buf(f, (char *) &nhdrs[0], sizeof(Elf_Nhdr));
 | |
|   write_buf(f, note_name, nhdrs[0].n_namesz);
 | |
|   write_buf(f, pad, PAD_LEN(nhdrs[0].n_namesz) - nhdrs[0].n_namesz);
 | |
|   write_buf(f, (char *) &mei, mei_len);
 | |
|   write_buf(f, pad, PAD_LEN(mei_len) - mei_len);
 | |
| 
 | |
|   /* Get registers */
 | |
|   if (sys_getregs(®s, fp->fp_endpoint) != OK)
 | |
| 	printf("VFS: Could not read registers\n");
 | |
| 
 | |
|   if (sizeof(regs) != gregs_len)
 | |
| 	printf("VFS: Wrong core register structure size\n");
 | |
| 
 | |
|   /* Dump second note entry - the general registers */
 | |
|   write_buf(f, (char *) &nhdrs[1], sizeof(Elf_Nhdr));
 | |
| 
 | |
|   write_buf(f, note_name, nhdrs[1].n_namesz);
 | |
|   write_buf(f, pad, PAD_LEN(nhdrs[1].n_namesz) - nhdrs[1].n_namesz);
 | |
|   write_buf(f, (char *) ®s, gregs_len);
 | |
|   write_buf(f, pad, PAD_LEN(gregs_len) - gregs_len);
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				dump_elf_header			             *
 | |
|  *===========================================================================*/
 | |
| static void dump_elf_header(struct filp *f, Elf_Ehdr elf_header)
 | |
| {
 | |
|   write_buf(f, (char *) &elf_header, sizeof(Elf_Ehdr));
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *			  dump_program_headers			             *
 | |
|  *===========================================================================*/
 | |
| static void dump_program_headers(struct filp *f, Elf_Phdr phdrs[], int phnum)
 | |
| {
 | |
|   int i;
 | |
| 
 | |
|   for (i = 0; i < phnum; i++)
 | |
| 	write_buf(f, (char *) &phdrs[i], sizeof(Elf_Phdr));
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *			      dump_segments 			             *
 | |
|  *===========================================================================*/
 | |
| static void dump_segments(struct filp *f, Elf_Phdr phdrs[], int phnum)
 | |
| {
 | |
|   int i;
 | |
|   vir_bytes len;
 | |
|   off_t off, seg_off;
 | |
|   int r;
 | |
|   static u8_t buf[CLICK_SIZE];
 | |
| 
 | |
|   for (i = 1; i < phnum; i++) {
 | |
| 	len = phdrs[i].p_memsz;
 | |
| 	seg_off = phdrs[i].p_vaddr;
 | |
| 
 | |
| 	if (len > LONG_MAX) {
 | |
| 		printf("VFS: segment too large to dump, truncating\n");
 | |
| 		len = LONG_MAX;
 | |
| 	}
 | |
| 
 | |
| 	for (off = 0; off < (off_t) len; off += CLICK_SIZE) {
 | |
| 		vir_bytes p = (vir_bytes) (seg_off + off);
 | |
| 		r = sys_vircopy(fp->fp_endpoint, p,
 | |
| 			SELF, (vir_bytes) buf,
 | |
| 			(phys_bytes) CLICK_SIZE);
 | |
| 
 | |
| 		if(r != OK) {
 | |
| 			/* memory didn't exist; write as zeroes */
 | |
| 			memset(buf, 0, sizeof(buf));
 | |
| 			continue;
 | |
| 		}
 | |
| 
 | |
| 		write_buf(f, (char *) buf, (off + CLICK_SIZE <= (off_t) len) ?
 | |
| 					CLICK_SIZE : (len - off));
 | |
| 	}
 | |
|   }
 | |
| }
 |