/*---------------------------------------------------------------------------* Project: TwlSDK - bin2obj File: object.c Copyright 2005-2008 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: 2008-09-18#$ $Rev: 8573 $ $Author: okubata_ryoma $ *---------------------------------------------------------------------------*/ #include "bin2obj.h" static void header_init(ELF32_ElfHeader * h, u16 machine, u8 endian); /*---------------------------------------------------------------------------* Name: object_init Description: Initializes object information. Arguments: obj Object Returns: TRUE for success; FALSE for failure. *---------------------------------------------------------------------------*/ void object_init(Object * obj, u16 machine, u8 endian) { ELF32_SectionHeader *s; ELF32_ElfHeader *h; //----------------------------------------------------------------------- // Initialize area ZERO //----------------------------------------------------------------------- memset(obj, 0, sizeof(Object)); //----------------------------------------------------------------------- // Initialization of Elf Header //----------------------------------------------------------------------- h = &obj->header; header_init(h, machine, endian); //----------------------------------------------------------------------- // Register default section //----------------------------------------------------------------------- // The section with index=0 is dummy=NULL (void)add_section(obj, NULL, SHT_NULL, 0, 0, 0); // index=1 section name table h->e_shstrndx = add_section(obj, ".shstrtab", SHT_STRTAB, SHF_NULL, obj->section_name.size, 0); // index=2 symbol info structure obj->symbol_index = add_section(obj, ".symtab", SHT_SYMTAB, SHF_NULL, 0, 4); // index=3 symbol name table obj->symbol_name_index = add_section(obj, ".strtab", SHT_STRTAB, SHF_NULL, obj->symbol_name.size, 1); // Add symbol information setting s = &obj->section[obj->symbol_index]; s->sh_link = obj->symbol_name_index; // symbol name table link s->sh_info = -1; // Initialization of symbol's last index value s->sh_entsize = sizeof(ELF32_Symbol); // symbol entry size //----------------------------------------------------------------------- // Symbol table initialization //----------------------------------------------------------------------- // Register index=0 NULL symbol (void)add_symbol(obj, NULL, 0, 0, 0); } /*---------------------------------------------------------------------------* Name: header_init Description: Creates ELF header info. Arguments: elfHeader ELF header info machine Machine code EM_ARM // ARM EM_PPC // PPC endian ELF's endian ELFDATA2LSB // Little Endian ELFDATA2MSB // Big Endian Returns: None. *---------------------------------------------------------------------------*/ static void header_init(ELF32_ElfHeader * h, u16 machine, u8 endian) { memset(h, 0, sizeof(ELF32_ElfHeader)); h->e_ident[0] = ELFMAG0; // 0x7f h->e_ident[1] = ELFMAG1; // 'E' h->e_ident[2] = ELFMAG2; // 'L' h->e_ident[3] = ELFMAG3; // 'F' h->e_ident[4] = ELFCLASS32; // 32 bit h->e_ident[5] = endian; // ELFDATA2MSB/ELFDATA2LSB h->e_ident[6] = EV_CURRENT; // CURRENT h->e_type = ET_REL; h->e_machine = machine; h->e_version = EV_CURRENT; h->e_entry = 0; h->e_phoff = 0; h->e_shoff = 0; // Fill in with correct values later h->e_flags = 0; h->e_ehsize = sizeof(ELF32_ElfHeader); h->e_phentsize = 0; h->e_phnum = 0; h->e_shentsize = sizeof(ELF32_SectionHeader); h->e_shnum = 0; // +1 each time section increases h->e_shstrndx = 0; // Fill in with correct values later return; } /*---------------------------------------------------------------------------* Name: map_section Description: Writes the section's location information. Arguments: obj Object Returns: None. *---------------------------------------------------------------------------*/ void map_section(Object * obj) { ELF32_ElfHeader *h; ELF32_SectionHeader *s; u32 offset; int i; // ELF HEADER/SECTION HEADER position calculation h = &obj->header; offset = h->e_ehsize; h->e_shoff = roundup(offset, 4); offset = h->e_shoff + h->e_shentsize * h->e_shnum; // Section's position calculation for (i = 1; i < obj->header.e_shnum; i++) { s = &obj->section[i]; s->sh_offset = roundup(offset, s->sh_addralign); offset = s->sh_offset + s->sh_size; } return; } /*---------------------------------------------------------------------------* Name: roundup Description: Rounds up integers. Arguments: val Value align Boundary value Returns: Result *---------------------------------------------------------------------------*/ u32 roundup(u32 val, u32 align) { if (align > 1) { u32 n = val % align; if (n > 0) { val += (align - n); } } return val; } /*---------------------------------------------------------------------------* Name: conv_to_big_endian Description: Convert to big-endian Arguments: src before conversion dest after conversion Returns: Result *---------------------------------------------------------------------------*/ static u32 Be32(u32 x) { return (u32)(((x) >> 24) & 0x000000ff) | (((x) >> 8) & 0x0000ff00) | (((x) << 8) & 0x00ff0000) | (((x) << 24) & 0xff000000); } static u16 Be16(u16 x) { return (u16)(((x) >> 8) & 0x00ff) | (((x) << 8) & 0xff00); } static void conv_to_big_endian_header(const ELF32_ElfHeader * src, ELF32_ElfHeader * dest) { memcpy(dest->e_ident, src->e_ident, EI_NIDENT); dest->e_type = Be16(src->e_type); dest->e_machine = Be16(src->e_machine); dest->e_version = Be32(src->e_version); dest->e_entry = Be32(src->e_entry); dest->e_phoff = Be32(src->e_phoff); dest->e_shoff = Be32(src->e_shoff); dest->e_flags = Be32(src->e_flags); dest->e_ehsize = Be16(src->e_ehsize); dest->e_phentsize = Be16(src->e_phentsize); dest->e_phnum = Be16(src->e_phnum); dest->e_shentsize = Be16(src->e_shentsize); dest->e_shnum = Be16(src->e_shnum); dest->e_shstrndx = Be16(src->e_shstrndx); } static void conv_to_big_endian_section(const ELF32_SectionHeader * src, ELF32_SectionHeader * dest) { dest->sh_name = Be32(src->sh_name); dest->sh_type = Be32(src->sh_type); dest->sh_flags = Be32(src->sh_flags); dest->sh_addr = Be32(src->sh_addr); dest->sh_offset = Be32(src->sh_offset); dest->sh_size = Be32(src->sh_size); dest->sh_link = Be32(src->sh_link); dest->sh_info = Be32(src->sh_info); dest->sh_addralign = Be32(src->sh_addralign); dest->sh_entsize = Be32(src->sh_entsize); } static void conv_to_big_endian_symbol(const ELF32_Symbol * src, ELF32_Symbol * dest) { dest->st_name = Be32(src->st_name); dest->st_value = Be32(src->st_value); dest->st_size = Be32(src->st_size); dest->st_info = src->st_info; dest->st_other = src->st_other; dest->st_shndx = Be16(src->st_shndx); } void conv_to_big_endian(const Object * src, Object * dest) { int i, n; conv_to_big_endian_header(&src->header, &dest->header); for (i = 0; i < src->header.e_shnum; i++) { conv_to_big_endian_section(&src->section[i], &dest->section[i]); } n = src->section[src->symbol_index].sh_size / sizeof(src->symbol[0]); for (i = 0; i < n; i++) { conv_to_big_endian_symbol(&src->symbol[i], &dest->symbol[i]); } }