#define ET_REL 1 /* Relocatable file */
+/* Values for e_machine field of Ehdr. */
+
+#define EM_SPARC 2 /* SUN SPARC */
+#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
+
/* Special section index values. */
#define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */
/* Compare two attributes structures. */
static const char *
-simple_object_elf_attributes_compare (void *data1, void *data2, int *err)
+simple_object_elf_attributes_merge (void *todata, void *fromdata, int *err)
{
- struct simple_object_elf_attributes *attrs1 =
- (struct simple_object_elf_attributes *) data1;
- struct simple_object_elf_attributes *attrs2 =
- (struct simple_object_elf_attributes *) data2;
-
- if (attrs1->ei_data != attrs2->ei_data
- || attrs1->ei_class != attrs2->ei_class
- || attrs1->machine != attrs2->machine)
+ struct simple_object_elf_attributes *to =
+ (struct simple_object_elf_attributes *) todata;
+ struct simple_object_elf_attributes *from =
+ (struct simple_object_elf_attributes *) fromdata;
+
+ if (to->ei_data != from->ei_data || to->ei_class != from->ei_class)
{
*err = 0;
return "ELF object format mismatch";
}
+
+ if (to->machine != from->machine)
+ {
+ int ok;
+
+ /* EM_SPARC and EM_SPARC32PLUS are compatible and force an
+ output of EM_SPARC32PLUS. */
+ ok = 0;
+ switch (to->machine)
+ {
+ case EM_SPARC:
+ if (from->machine == EM_SPARC32PLUS)
+ {
+ to->machine = from->machine;
+ ok = 1;
+ }
+ break;
+
+ case EM_SPARC32PLUS:
+ if (from->machine == EM_SPARC)
+ ok = 1;
+ break;
+
+ default:
+ break;
+ }
+
+ if (!ok)
+ {
+ *err = 0;
+ return "ELF machine number mismatch";
+ }
+ }
+
return NULL;
}
unsigned char buf[sizeof (Elf64_External_Ehdr)];
simple_object_write_section *section;
unsigned int shnum;
+ unsigned int shstrndx;
fns = attrs->type_functions;
cl = attrs->ei_class;
(cl == ELFCLASS32
? sizeof (Elf32_External_Shdr)
: sizeof (Elf64_External_Shdr)));
- ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shnum, Elf_Half, shnum);
- ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shstrndx, Elf_Half,
- shnum == 0 ? 0 : shnum - 1);
+ ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shnum, Elf_Half,
+ shnum >= SHN_LORESERVE ? 0 : shnum);
+ if (shnum == 0)
+ shstrndx = 0;
+ else
+ {
+ shstrndx = shnum - 1;
+ if (shstrndx >= SHN_LORESERVE)
+ shstrndx = SHN_XINDEX;
+ }
+ ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shstrndx, Elf_Half, shstrndx);
return simple_object_internal_write (descriptor, 0, buf, ehdr_size,
errmsg, err);
off_t offset, unsigned int sh_name,
unsigned int sh_type, unsigned int sh_flags,
unsigned int sh_offset, unsigned int sh_size,
- unsigned int sh_addralign, const char **errmsg,
- int *err)
+ unsigned int sh_link, unsigned int sh_addralign,
+ const char **errmsg, int *err)
{
struct simple_object_elf_attributes *attrs =
(struct simple_object_elf_attributes *) sobj->data;
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_flags, Elf_Addr, sh_flags);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_offset, Elf_Addr, sh_offset);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_size, Elf_Addr, sh_size);
- /* sh_link left as zero. */
+ ELF_SET_FIELD (fns, cl, Shdr, buf, sh_link, Elf_Word, sh_link);
/* sh_info left as zero. */
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign);
/* sh_entsize left as zero. */
unsigned int shnum;
size_t shdr_offset;
size_t sh_offset;
+ unsigned int first_sh_size;
+ unsigned int first_sh_link;
size_t sh_name;
unsigned char zero;
shdr_offset = ehdr_size;
sh_offset = shdr_offset + shnum * shdr_size;
+ if (shnum < SHN_LORESERVE)
+ first_sh_size = 0;
+ else
+ first_sh_size = shnum;
+ if (shnum - 1 < SHN_LORESERVE)
+ first_sh_link = 0;
+ else
+ first_sh_link = shnum - 1;
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
- 0, 0, 0, 0, 0, 0, &errmsg, err))
+ 0, 0, 0, 0, first_sh_size, first_sh_link,
+ 0, &errmsg, err))
return errmsg;
shdr_offset += shdr_size;
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
sh_name, SHT_PROGBITS, 0, sh_offset,
- sh_size, 1U << section->align,
+ sh_size, 0, 1U << section->align,
&errmsg, err))
return errmsg;
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
sh_name, SHT_STRTAB, 0, sh_offset,
- sh_name + strlen (".shstrtab") + 1,
+ sh_name + strlen (".shstrtab") + 1, 0,
1, &errmsg, err))
return errmsg;
simple_object_elf_find_sections,
simple_object_elf_fetch_attributes,
simple_object_elf_release_read,
- simple_object_elf_attributes_compare,
+ simple_object_elf_attributes_merge,
simple_object_elf_release_attributes,
simple_object_elf_start_write,
simple_object_elf_write_to_file,