コード例 #1
0
void parse_elf (char* file_name)
{
	init_elf_parser (file_name);

	if (architecture == ELFCLASS32)
	{
		get_num_sections ();
		get_section_names ();
		parse_sections ();
		find_main ();
	}
	else
	{
		get_num_sections64 ();
		get_section_names64 ();
		parse_sections64 ();
		find_main64 ();
	}
}
コード例 #2
0
ファイル: elf32.c プロジェクト: gz/aos10
int
elf32_write(struct edit_file *efile, struct edit_options *opts)
{
	FILE *fptr;
	int file_size, data_start, next_data, shdr_start, i, j;
	struct edit_segment *segs = efile->segments;
	uint32_t e_shnum;
	Elf32_Ehdr ehdr;
	Elf32_Shdr shdr;
	Elf32_Phdr phdr;
	int binfo_offset = 0;
	/* If the file hasn't been modified, then just return -- do NOT unmap the file */
	if (!(efile->flags & FL_MOD))
		return 0;

	/* File has been modified, so need to write back to disk */
	if ((fptr = fopen(efile->filename, "wb")) == NULL) {
		/* FIXME (sjw Wed Jul 19 05:24:41 2000 ) --- Should give more info here */
		log(LOG_CRITICAL, "Couldn't open target file '%s'",
			efile->filename);
		return 1;
	}

	/* Find size of file -- include space for header.  Segments will be calculated later */
	shdr_start = next_data = data_start = file_size =
		sizeof(Elf32_Ehdr) + (sizeof(Elf32_Phdr) * (efile->nsegments));

	for (i = 0; i < efile->nsegments; i++)
		shdr_start += segs[i].filesize;
	shdr_start = ALIGN(shdr_start, 4);
	memset(&ehdr, 0, sizeof(Elf32_Ehdr));

	/* Write out header */
	ehdr.e_ident[0] = ELF_MAGIC_0;
	ehdr.e_ident[1] = ELF_MAGIC_1;
	ehdr.e_ident[2] = ELF_MAGIC_2;
	ehdr.e_ident[3] = ELF_MAGIC_3;

	ehdr.e_ident[EI_CLASS] = ELFCLASS32;
	ehdr.e_ident[EI_DATA] =
		(efile->endianness == LSB ? ELFDATA2LSB : ELFDATA2MSB);
	ehdr.e_ident[EI_VERSION] = EV_CURRENT;

	write16(ET_EXEC, &(ehdr.e_type), efile->endianness);
	write16(arch2elfmach(efile->arch), &(ehdr.e_machine),
			efile->endianness);
	write32(EV_CURRENT, &(ehdr.e_version), efile->endianness);

	write32(efile->entry + opts->elf_hdr_physaddr, &(ehdr.e_entry), efile->endianness);
	write32(sizeof(Elf32_Ehdr), &(ehdr.e_phoff), efile->endianness);
	write32(shdr_start, &(ehdr.e_shoff), efile->endianness);
	write32(elfarchflags(efile->arch), &(ehdr.e_flags), efile->endianness);
	write16(sizeof(Elf32_Ehdr), &(ehdr.e_ehsize), efile->endianness);
	write16(sizeof(Elf32_Phdr), &(ehdr.e_phentsize), efile->endianness);

	/* FIXME (sjw Wed Jul 19 05:16:11 2000 ) --- Should I include the PHDR segment (spec says not to, I _think_) */
	write16(efile->nsegments, &(ehdr.e_phnum), efile->endianness);
	write16(sizeof(Elf32_Shdr), &(ehdr.e_shentsize), efile->endianness);

	/* Calculate number of section headers: 3 more than actual amount
	 * because we have to create a section header string table and a "null" entry, and binfo*/
	e_shnum = get_num_sections(efile) + 3;
	write16(e_shnum, &(ehdr.e_shnum), efile->endianness);
	write16(e_shnum - 1, &(ehdr.e_shstrndx), efile->endianness); /* -1 for 0-based index */

	/* Write header to the file */
	if (fwrite(&(ehdr), sizeof(Elf32_Ehdr), 1, fptr) != 1) {
		log(LOG_CRITICAL, "Could not write Ehdr to '%s' (%d)\n",
			efile->filename, ferror(fptr));
		return 1;
	}

	memset(&phdr, 0, sizeof(Elf32_Phdr));

	/* Set up data that doesn't change between segments */
	write32(PT_LOAD, &(phdr.p_type), efile->endianness);

	/* Write out segment headers, and update next_data */
	for (i = 0; i < efile->nsegments; i++) {
		/* FIXME (sjw Tue Aug 15 00:46:39 2000 ) --- This isn't 'properly' aligned */

		/* FIXME (sjw Wed Jul 19 10:04:12 2000 ) --- Flags */
		write32(PF_X | PF_R | PF_W, &(phdr.p_flags), efile->endianness);
		
		write32(next_data, &(phdr.p_offset), efile->endianness);
		if (i == efile->binfo_seg_ind) {
			binfo_offset = next_data;
		}
                /* XXX: We shift the vaddr to work around PMON loading segments
                 * into vaddrs on MIPS.  Since some segments (the kernel) are
                 * already in kseg0, we use bitwise or to leave them alone.
                 * -- alexw */
		write32(segs[i].vaddr | opts->elf_hdr_virtaddr, &(phdr.p_vaddr), efile->endianness);
		write32(segs[i].paddr + opts->elf_hdr_physaddr, &(phdr.p_paddr), efile->endianness);
		write32(segs[i].filesize, &(phdr.p_filesz), efile->endianness);
		write32(segs[i].memsize, &(phdr.p_memsz), efile->endianness);
		write32(segs[i].align, &(phdr.p_align), efile->endianness);

		/* Write out header to the file */
		if (fwrite(&phdr, sizeof(Elf32_Phdr), 1, fptr) != 1) {
			log(LOG_CRITICAL, "Could not write Phdr to '%s' (%d) (\n",
				efile->filename, ferror(fptr));
			return 1;
		}

		next_data += segs[i].filesize;
	}

	/* Write out the actual data */
	next_data = data_start;
	for (i = 0; i < efile->nsegments; i++) {

		if (segs[i].flags & FL_S_PATCH_DIT && (!(efile->flags & FL_NODIT))) {
			void *write_at = segs[i].data +
				(segs[i].patch_addr - segs[i].vaddr);
			writeword(efile->arch, efile->dit_header_segment->paddr,
					  write_at, efile->endianness);
		}
		/* nfd: Don't try writing if we have a data size of 0 */
		if (segs[i].filesize != 0
			&& fwrite(segs[i].data, segs[i].filesize, 1, fptr) != 1) {
			log(LOG_CRITICAL, "Could not write data to '%s' (%d)\n",
				efile->filename, ferror(fptr));
			return 1;
		}

		next_data += segs[i].filesize;
	}

	/* Fixup offsets of existing sections. */
	/*shdr_start = next_data = data_start = file_size =
		sizeof(Elf32_Ehdr) + (sizeof(Elf32_Phdr) * (efile->nsegments));

	for (i = 0; i < efile->nsegments; i++)
		shdr_start += segs[i].filesize;*/
	struct edit_section *current_section;
	for (i = 0; i < efile->nsegments; i++) {
		for (current_section = efile->first_section;
		     current_section;
		     current_section = current_section -> next) {
			if (current_section->segment_num == i) {
				/* Fixup this section... */
				current_section->output_offset = 
					sizeof(Elf32_Ehdr) + (sizeof(Elf32_Phdr) * (efile->nsegments));
				for (j=0; j < i; j++) {
					current_section->output_offset += segs[j].filesize;
				}
				current_section->output_offset += current_section->segment_offset;
			}
		}
	}

	/* We construct two dummy section headers:
	 * - section header 0, which is empty;
	 * - section header string table.
	*/
	/* ... first section */
	fseek(fptr, shdr_start, SEEK_SET);
	current_section = calloc(1, sizeof(struct edit_section));
	current_section->next = efile->first_section;
	efile->first_section = current_section;
	/* ... final section */

	while(current_section->next != NULL) {
		current_section = current_section->next;
	}

	current_section = current_section->next = calloc(1, sizeof(struct edit_section));
	current_section->type = SHT_PROGBITS;
	current_section->addr = segs[efile->binfo_seg_ind].paddr;
	assert(binfo_offset != 0);
	current_section->output_offset = binfo_offset;
	current_section->addralign = 0x1000;
	current_section->entsize = 0;
	current_section->flags = SHF_ALLOC;
	current_section->size = efile->binfo_size;
	strcpy(current_section->name, ".binfo");

	uint32_t strtab_size = 1;
	current_section = efile->first_section; /* Get first after null segment */
	while(current_section->next != NULL) {
		strtab_size += strlen(current_section->name) + 1;
		current_section = current_section->next;
	}
	strtab_size += strlen(current_section->name) + 1;
	current_section = current_section->next = calloc(1, sizeof(struct edit_section));
	current_section->type = SHT_STRTAB;
	current_section->addr = 0;
	current_section->output_offset = shdr_start + (sizeof(shdr) * e_shnum);
	current_section->addralign = 1;
	current_section->entsize = 0;
	current_section->flags = 0;
	strcpy(current_section->name, ".shstrtab");
	strtab_size += strlen(current_section->name) + 1;
	current_section->size = strtab_size;

	/* Write out the section headers */
	current_section = efile->first_section;
	uint32_t shstrndx_pos = 1;
	while(current_section) {
		/* name, type, addr, size, addralign, entsize */
		
		write32(shstrndx_pos, &(shdr.sh_name), efile->endianness);
		write32(current_section->type, &(shdr.sh_type), efile->endianness);
		write32(current_section->flags, &(shdr.sh_flags), efile->endianness);
		write32(current_section->addr, &(shdr.sh_addr), efile->endianness);
		write32(current_section->output_offset, &(shdr.sh_offset), efile->endianness); /* FIXME! */
		write32(current_section->size, &(shdr.sh_size), efile->endianness);
		write32(0, &(shdr.sh_link), efile->endianness);
		write32(0, &(shdr.sh_info), efile->endianness);
		write32(current_section->addralign, &(shdr.sh_addralign), efile->endianness);
		write32(current_section->entsize, &(shdr.sh_entsize), efile->endianness);
		if (fwrite(&shdr, sizeof(Elf32_Shdr), 1, fptr) != 1) {
			log(LOG_CRITICAL, "Could not write Shdr to '%s' (%d)\n",
				efile->filename, ferror(fptr));
			return 1;
		}
		shstrndx_pos += strlen(current_section->name) + 1;
		current_section = current_section->next;
	}

	/* We need to add a section for the bootinfo */

	/* ... finally, the section header string table itself. */
	current_section = efile->first_section;
	/* String table always begins with a null. */
	fwrite("\0", 1, 1, fptr);
	while(current_section) {
		int namelen;
		namelen = strlen(current_section->name);
		if (namelen > 0) {
			fwrite(current_section->name, 1, namelen, fptr);
		}
		fwrite("\0", 1, 1, fptr);
		current_section = current_section->next;
	}
	fclose(fptr);

	return 0;
}