Example #1
0
File: notes.c Project: botord/perf
int read_build_id(void *note_data, size_t note_len, void *bf, size_t size)
{
 
    struct {
        u32 n_namesz;
        u32 n_descsz;
        u32 n_type;
    } *nhdr;

    void *ptr;
    
    printf("begin: sizeof(nhdr) = %d\n", sizeof(*nhdr));

    ptr = note_data;
    while (ptr < (note_data + note_len)) {
        const char *name, *desc;
        size_t namesz, descsz;

        printf("ptr: 0x%X\n", (unsigned int)ptr);

        nhdr = ptr;
        namesz = NOTE_ALIGN(nhdr->n_namesz);
        descsz = NOTE_ALIGN(nhdr->n_descsz);
        printf("namesz: %u\ndescsz: %u\n", namesz, descsz);
        ptr += sizeof(*nhdr);
        name = ptr;
        printf("name: %s\n", name);
        ptr += namesz;
        desc = ptr;
        printf("desc: %s\n", desc);
        if (nhdr->n_type == 3 && nhdr->n_namesz == sizeof("GNU")) {
            if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
                size_t sz = min(size, descsz);
                memcpy(bf, ptr, sz);
                memset(bf + sz, 0, size - sz);
                printf("found GNU!\n");
                return 0;
            }
        }
        ptr += descsz;
    }
    return -1;
}
Example #2
0
static int read_build_id(void *note_data, size_t note_len, void *bf,
			 size_t size, bool need_swap)
{
	struct {
		u32 n_namesz;
		u32 n_descsz;
		u32 n_type;
	} *nhdr;
	void *ptr;

	ptr = note_data;
	while (ptr < (note_data + note_len)) {
		const char *name;
		size_t namesz, descsz;

		nhdr = ptr;
		if (need_swap) {
			nhdr->n_namesz = bswap_32(nhdr->n_namesz);
			nhdr->n_descsz = bswap_32(nhdr->n_descsz);
			nhdr->n_type = bswap_32(nhdr->n_type);
		}

		namesz = NOTE_ALIGN(nhdr->n_namesz);
		descsz = NOTE_ALIGN(nhdr->n_descsz);

		ptr += sizeof(*nhdr);
		name = ptr;
		ptr += namesz;
		if (nhdr->n_type == NT_GNU_BUILD_ID &&
		    nhdr->n_namesz == sizeof("GNU")) {
			if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
				size_t sz = min(size, descsz);
				memcpy(bf, ptr, sz);
				memset(bf + sz, 0, size - sz);
				return 0;
			}
		}
		ptr += descsz;
	}

	return -1;
}
Example #3
0
size_t
gelf_getnote (Elf_Data *data, size_t offset, GElf_Nhdr *result,
	      size_t *name_offset, size_t *desc_offset)
{
  if (data == NULL)
    return 0;

  if (unlikely (data->d_type != ELF_T_NHDR))
    {
      __libelf_seterrno (ELF_E_INVALID_HANDLE);
      return 0;
    }

  /* It's easy to handle this type.  It has the same size for 32 and
     64 bit objects.  */
  assert (sizeof (GElf_Nhdr) == sizeof (Elf32_Nhdr));
  assert (sizeof (GElf_Nhdr) == sizeof (Elf64_Nhdr));

  rwlock_rdlock (((Elf_Data_Scn *) data)->s->elf->lock);

  /* The data is already in the correct form.  Just make sure the
     offset is OK.  */
  if (unlikely (offset > data->d_size
		|| data->d_size - offset < sizeof (GElf_Nhdr)))
    {
      __libelf_seterrno (ELF_E_OFFSET_RANGE);
      offset = 0;
    }
  else
    {
      const GElf_Nhdr *n = data->d_buf + offset;
      offset += sizeof *n;

      /* Include padding.  Check below for overflow.  */
      GElf_Word namesz = NOTE_ALIGN (n->n_namesz);
      GElf_Word descsz = NOTE_ALIGN (n->n_descsz);

      if (unlikely (offset > data->d_size
		    || data->d_size - offset < namesz
		    || (namesz == 0 && n->n_namesz != 0)))
	offset = 0;
      else
	{
	  *name_offset = offset;
	  offset += namesz;
	  if (unlikely (offset > data->d_size
			|| data->d_size - offset < descsz
			|| (descsz == 0 && n->n_descsz != 0)))
	    offset = 0;
	  else
	    {
	      *desc_offset = offset;
	      offset += descsz;
	      *result = *n;
	    }
	}
    }

  rwlock_unlock (((Elf_Data_Scn *) data)->s->elf->lock);

  return offset;
}
static bool get_build_id(
    Backtrace* backtrace, uintptr_t base_addr, uint8_t* e_ident, std::string* build_id) {
  HdrType hdr;

  memcpy(&hdr.e_ident[0], e_ident, EI_NIDENT);

  // First read the rest of the header.
  if (backtrace->Read(base_addr + EI_NIDENT, reinterpret_cast<uint8_t*>(&hdr) + EI_NIDENT,
                      sizeof(HdrType) - EI_NIDENT) != sizeof(HdrType) - EI_NIDENT) {
    return false;
  }

  for (size_t i = 0; i < hdr.e_phnum; i++) {
    PhdrType phdr;
    if (backtrace->Read(base_addr + hdr.e_phoff + i * hdr.e_phentsize,
                        reinterpret_cast<uint8_t*>(&phdr), sizeof(phdr)) != sizeof(phdr)) {
      return false;
    }
    // Looking for the .note.gnu.build-id note.
    if (phdr.p_type == PT_NOTE) {
      size_t hdr_size = phdr.p_filesz;
      uintptr_t addr = base_addr + phdr.p_offset;
      while (hdr_size >= sizeof(NhdrType)) {
        NhdrType nhdr;
        if (backtrace->Read(addr, reinterpret_cast<uint8_t*>(&nhdr), sizeof(nhdr)) != sizeof(nhdr)) {
          return false;
        }
        addr += sizeof(nhdr);
        if (nhdr.n_type == NT_GNU_BUILD_ID) {
          // Skip the name (which is the owner and should be "GNU").
          addr += NOTE_ALIGN(nhdr.n_namesz);
          uint8_t build_id_data[128];
          if (nhdr.n_namesz > sizeof(build_id_data)) {
            ALOGE("Possible corrupted note, name size value is too large: %u",
                  nhdr.n_namesz);
            return false;
          }
          if (backtrace->Read(addr, build_id_data, nhdr.n_descsz) != nhdr.n_descsz) {
            return false;
          }

          build_id->clear();
          for (size_t bytes = 0; bytes < nhdr.n_descsz; bytes++) {
            *build_id += android::base::StringPrintf("%02x", build_id_data[bytes]);
          }

          return true;
        } else {
          // Move past the extra note data.
          hdr_size -= sizeof(nhdr);
          size_t skip_bytes = NOTE_ALIGN(nhdr.n_namesz) + NOTE_ALIGN(nhdr.n_descsz);
          addr += skip_bytes;
          if (hdr_size < skip_bytes) {
            break;
          }
          hdr_size -= skip_bytes;
        }
      }
    }
  }
  return false;
}