Exemplo n.º 1
0
/**
  MIPS ABI Supplement:

  DT_PLTGOT This member holds the address of the .got section.

  DT_MIPS_SYMTABNO This member holds the number of entries in the
  .dynsym section.

  DT_MIPS_LOCAL_GOTNO This member holds the number of local global
  offset table entries.

  DT_MIPS_GOTSYM This member holds the index of the first dyamic
  symbol table entry that corresponds to an entry in the gobal offset
  table.

 */
int
arch_elf_init(struct ltelf *lte, struct library *lib)
{
	Elf_Scn *scn;
	GElf_Shdr shdr;

	/* FIXME: for CPIC we should really scan both GOT tables
	 * to pick up relocations to external functions.  Right now
	 * function pointers from the main binary to external functions
	 * can't be traced in CPIC mode.  */
	if (mips_elf_is_cpic(lte->ehdr.e_flags)) {
		return 0; /* We are already done.  */
	}

	if (elf_get_section_type(lte, SHT_DYNAMIC, &scn, &shdr) < 0
	    || scn == NULL) {
	fail:
		error(0, 0, "Couldn't get SHT_DYNAMIC: %s",
		      elf_errmsg(-1));
		return -1;
	}

	Elf_Data *data = elf_loaddata(scn, &shdr);
	if (data == NULL)
		goto fail;

	size_t j;
	for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
		GElf_Dyn dyn;
		if (gelf_getdyn(data, j, &dyn) == NULL)
			goto fail;

		if(dyn.d_tag == DT_PLTGOT) {
			lte->arch.pltgot_addr = dyn.d_un.d_ptr;
		}
		if(dyn.d_tag == DT_MIPS_LOCAL_GOTNO){
			lte->arch.mips_local_gotno = dyn.d_un.d_val;
		}
		if(dyn.d_tag == DT_MIPS_GOTSYM){
			lte->arch.mips_gotsym = dyn.d_un.d_val;
		}
	}

	/* Tell the generic code how many dynamic trace:able symbols
	 * we've got.  */
	lte->relplt_count = lte->dynsym_count - lte->arch.mips_gotsym;
	return 0;
}
Exemplo n.º 2
0
int
arch_elf_init(struct ltelf *lte, struct library *lib)
{
	/* Nothing in this section is strictly critical.  It's not
	 * that much of a deal if we fail to guess right whether the
	 * ABI is softfp or hardfp.  */
	unsigned hardfp = 0;

	Elf_Scn *scn;
	Elf_Data *data;
	GElf_Shdr shdr;
	if (elf_get_section_type(lte, SHT_ARM_ATTRIBUTES, &scn, &shdr) < 0
	    || (scn != NULL && (data = elf_loaddata(scn, &shdr)) == NULL)) {
		fprintf(stderr,
			"Error when obtaining ARM attribute section: %s\n",
			elf_errmsg(-1));
		goto done;

	} else if (scn != NULL && data != NULL) {
		GElf_Xword offset = 0;
		uint8_t version;
		if (elf_read_next_u8(data, &offset, &version) < 0) {
			goto done;
		} else if (version != 'A') {
			fprintf(stderr, "Unsupported ARM attribute section "
				"version %d ('%c').\n", version, version);
			goto done;
		}

		do {
			const char signature[] = "aeabi";
			/* N.B. LEN is including the length field
			 * itself.  */
			uint32_t sec_len;
			if (elf_read_u32(data, offset, &sec_len) < 0
			    || !elf_can_read_next(data, offset, sec_len)) {
				goto done;
			}
			const GElf_Xword next_offset = offset + sec_len;
			offset += 4;

			if (sec_len < 4 + sizeof signature
			    || strcmp(signature, data->d_buf + offset) != 0)
				goto skip;
			offset += sizeof signature;

			const GElf_Xword offset0 = offset;
			uint64_t tag;
			uint32_t sub_len;
			if (elf_read_next_uleb128(data, &offset, &tag) < 0
			    || elf_read_next_u32(data, &offset, &sub_len) < 0
			    || !elf_can_read_next(data, offset0, sub_len))
				goto done;

			if (tag != 1)
				/* IHI0045D_ABI_addenda: "section and
				 * symbol attributes are deprecated
				 * [...] consumers are permitted to
				 * ignore them."  */
				goto skip;

			while (offset < offset0 + sub_len) {
				if (elf_read_next_uleb128(data,
							  &offset, &tag) < 0)
					goto done;

				switch (tag) {
					uint64_t v;
				case 6: /* Tag_CPU_arch */
				case 7: /* Tag_CPU_arch_profile */
				case 8: /* Tag_ARM_ISA_use */
				case 9: /* Tag_THUMB_ISA_use */
				case 10: /* Tag_FP_arch */
				case 11: /* Tag_WMMX_arch */
				case 12: /* Tag_Advanced_SIMD_arch */
				case 13: /* Tag_PCS_config */
				case 14: /* Tag_ABI_PCS_R9_use */
				case 15: /* Tag_ABI_PCS_RW_data */
				case 16: /* Tag_ABI_PCS_RO_data */
				case 17: /* Tag_ABI_PCS_GOT_use */
				case 18: /* Tag_ABI_PCS_wchar_t */
				case 19: /* Tag_ABI_FP_rounding */
				case 20: /* Tag_ABI_FP_denormal */
				case 21: /* Tag_ABI_FP_exceptions */
				case 22: /* Tag_ABI_FP_user_exceptions */
				case 23: /* Tag_ABI_FP_number_model */
				case 24: /* Tag_ABI_align_needed */
				case 25: /* Tag_ABI_align_preserved */
				case 26: /* Tag_ABI_enum_size */
				case 27: /* Tag_ABI_HardFP_use */
				case 28: /* Tag_ABI_VFP_args */
				case 29: /* Tag_ABI_WMMX_args */
				case 30: /* Tag_ABI_optimization_goals */
				case 31: /* Tag_ABI_FP_optimization_goals */
				case 32: /* Tag_compatibility */
				case 34: /* Tag_CPU_unaligned_access */
				case 36: /* Tag_FP_HP_extension */
				case 38: /* Tag_ABI_FP_16bit_format */
				case 42: /* Tag_MPextension_use */
				case 70: /* Tag_MPextension_use as well */
				case 44: /* Tag_DIV_use */
				case 64: /* Tag_nodefaults */
				case 66: /* Tag_T2EE_use */
				case 68: /* Tag_Virtualization_use */
				uleb128:
					if (elf_read_next_uleb128
						(data, &offset, &v) < 0)
						goto done;
					if (tag == 28)
						hardfp = get_hardfp(v);
					if (tag != 32)
						continue;

					/* Tag 32 has two arguments,
					 * fall through.  */

				case 4:	/* Tag_CPU_raw_name */
				case 5:	/* Tag_CPU_name */
				case 65: /* Tag_also_compatible_with */
				case 67: /* Tag_conformance */
				ntbs:
					offset += strlen(data->d_buf
							 + offset) + 1;
					continue;
				}

				/* Handle unknown tags in a generic
				 * manner, if possible.  */
				if (tag <= 32) {
					fprintf(stderr,
						"Unknown tag %lld "
						"at offset %#llx "
						"of ARM attribute section.",
						tag, offset);
					goto skip;
				} else if (tag % 2 == 0) {
					goto uleb128;
				} else {
					goto ntbs;
				}
			}

		skip:
			offset = next_offset;

		} while (elf_can_read_next(data, offset, 1));

	}

done:
	lib->arch.hardfp = hardfp;
	return 0;
}