blob: a4da4c6873147492e940f24b90f549e111e1ba01 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_LIB_ZXDUMP_INCLUDE_LIB_ZXDUMP_ELF_SEARCH_H_
#define SRC_LIB_ZXDUMP_INCLUDE_LIB_ZXDUMP_ELF_SEARCH_H_
#include <lib/elfldltl/layout.h>
#include <lib/fit/result.h>
#include <lib/stdcompat/span.h>
#include <zircon/syscalls/object.h>
#include <optional>
#include <string>
#include <utility>
#include "buffer.h"
#include "dump.h"
#include "task.h"
#include "types.h"
namespace zxdump {
// Zircon core dumps are always in the 64-bit little-endian ELF format.
using Elf = elfldltl::Elf64<elfldltl::ElfData::k2Lsb>;
// This can be used from a zxdump::SegmentCallback function to guess if it's
// likely worthwhile to probe this mapping for containing the beginning of an
// ELF image. If this returns true, a zxdump::ProcessDump::FindBuildIdNote
// call on the segment is recommended.
bool IsLikelyElfMapping(const zx_info_maps_t& maps);
// These helpers are used by zxdump::ProcessDump::FindBuildIdNote, which is
// used in `prune_segment` callbacks for zxdump::ProcessDump::CollectProcess.
// But they can also be used separately.
// Try to detect an ELF image in this segment. If one is found and its phdrs
// are accessible, return a view into them from process.read_memory (which see
// about the lifetime of the buffer). Its ELF header can be fetched with
// process.read_memory<Elf::Ehdr>(segment.base).
fit::result<Error, Buffer<Elf::Phdr>> DetectElf( //
Process& process, const zx_info_maps_t& segment);
// This is the return value of zxdump::DetectElfIdentity, below. It contains
// absolute memory ranges in the process that provide identifying information.
struct ElfIdentity {
static constexpr size_t kBuildIdOffset = sizeof(Elf::Nhdr) + sizeof("GNU");
// This gives the vaddr and size of the ELF build ID note in memory. The
// size is zero if no build ID note was found. The memory there can be read
// out and the note header parsed to find the ID payload. The note header
// and name together have a fixed known size before the build ID bytes so
// that can just be skipped to extract only the actual ID bytes.
SegmentDisposition::Note build_id;
// This gives the vaddr and size of the DT_SONAME string (without its NUL
// terminator). The size is zero if no valid DT_SONAME string was found.
// (This reuses the vaddr, size pair type for the string's range in memory,
// but note not a note.)
SegmentDisposition::Note soname;
};
// Given a detected ELF image, examine its program headers and memory to find
// the build ID note and DT_SONAME string if possible. The argument span
// doesn't have to be one returned by DetectElf (i.e. by process.read_memory)
// but it can be.
fit::result<Error, ElfIdentity> DetectElfIdentity( //
Process& process, const zx_info_maps_t& segment, cpp20::span<const Elf::Phdr> phdrs);
// This uses zxdump::DetectElf to search a range of the address space for an
// ELF image. It returns a {first, last} pair giving the [first, last)
// subrange of the argument range that holds an ELF image. It returns the pair
// {last, last} if none is found. If it encounters errors, it returns {it, it}
// pointing to the segment where zxdump::DetectElf or zxdump::DetectElfIdentity
// returned an error.
using MapsInfoSpanIterator = cpp20::span<const zx_info_maps_t>::iterator;
using ElfSearchResult = std::pair<MapsInfoSpanIterator, MapsInfoSpanIterator>;
ElfSearchResult ElfSearch(Process& process, MapsInfoSpanIterator first, MapsInfoSpanIterator last);
} // namespace zxdump
#endif // SRC_LIB_ZXDUMP_INCLUDE_LIB_ZXDUMP_ELF_SEARCH_H_