[libcamera-devel] [PATCH 2/2] libcamera: ipa_module: elfLoadSymbol find symbol regardless of size
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Mon Jul 1 19:43:49 CEST 2019
Hi Paul,
Thank you for the patch.
On Mon, Jul 01, 2019 at 11:13:36PM +0900, Paul Elder wrote:
> Make elfLoadSymbol more generic by making the symbol size an output
> rather than an input. Also move the memcpy out of elfLoadSymbol.
>
> If the size of struct IPAModuleInfo changes between versions, we still
> want to be able to load it and perhaps do conversions for backwards
> compatibility. In this case the size should not be a restriction when
> searching for the symbol.
>
> Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
> ---
> src/libcamera/ipa_module.cpp | 64 ++++++++++++++++++++++--------------
> 1 file changed, 40 insertions(+), 24 deletions(-)
>
> diff --git a/src/libcamera/ipa_module.cpp b/src/libcamera/ipa_module.cpp
> index 5a46ec3..d82ac69 100644
> --- a/src/libcamera/ipa_module.cpp
> +++ b/src/libcamera/ipa_module.cpp
> @@ -17,6 +17,8 @@
> #include <sys/types.h>
> #include <unistd.h>
>
> +#include <tuple>
> +
No need to separate this from the previous headers, it can fit between
sys/types.h and unistd.h.
> #include "log.h"
> #include "pipeline_handler.h"
>
> @@ -81,18 +83,27 @@ int elfVerifyIdent(void *map, size_t soSize)
> return 0;
> }
>
> +/**
> + * \brief Retrieve address and size of a symbol from an mmap'ed ELF file
> + * \param[in] map Address of mmap'ed ELF file
> + * \param[in] soSize Size of mmap'ed ELF file (in bytes)
> + * \param[in] symbol Symbol name
> + *
> + * \return zero or error code, address or nullptr, size of symbol or zero,
> + * respectively
> + */
> template<class ElfHeader, class SecHeader, class SymHeader>
> -int elfLoadSymbol(void *dst, size_t size, void *map, size_t soSize,
> - const char *symbol)
> +std::tuple<int, void *, size_t>
> +elfLoadSymbol(void *map, size_t soSize, const char *symbol)
> {
> ElfHeader *eHdr = elfPointer<ElfHeader>(map, 0, soSize);
> if (!eHdr)
> - return -ENOEXEC;
> + return std::make_tuple(-ENOEXEC, nullptr, 0);
>
> off_t offset = eHdr->e_shoff + eHdr->e_shentsize * eHdr->e_shstrndx;
> SecHeader *sHdr = elfPointer<SecHeader>(map, offset, soSize);
> if (!sHdr)
> - return -ENOEXEC;
> + return std::make_tuple(-ENOEXEC, nullptr, 0);
> off_t shnameoff = sHdr->sh_offset;
>
> /* Locate .dynsym section header. */
> @@ -101,12 +112,12 @@ int elfLoadSymbol(void *dst, size_t size, void *map, size_t soSize,
> offset = eHdr->e_shoff + eHdr->e_shentsize * i;
> sHdr = elfPointer<SecHeader>(map, offset, soSize);
> if (!sHdr)
> - return -ENOEXEC;
> + return std::make_tuple(-ENOEXEC, nullptr, 0);
>
> offset = shnameoff + sHdr->sh_name;
> char *name = elfPointer<char[8]>(map, offset, soSize);
> if (!name)
> - return -ENOEXEC;
> + return std::make_tuple(-ENOEXEC, nullptr, 0);
>
> if (sHdr->sh_type == SHT_DYNSYM && !strcmp(name, ".dynsym")) {
> dynsym = sHdr;
> @@ -116,13 +127,13 @@ int elfLoadSymbol(void *dst, size_t size, void *map, size_t soSize,
>
> if (dynsym == nullptr) {
> LOG(IPAModule, Error) << "ELF has no .dynsym section";
> - return -ENOEXEC;
> + return std::make_tuple(-ENOEXEC, nullptr, 0);
> }
>
> offset = eHdr->e_shoff + eHdr->e_shentsize * dynsym->sh_link;
> sHdr = elfPointer<SecHeader>(map, offset, soSize);
> if (!sHdr)
> - return -ENOEXEC;
> + return std::make_tuple(-ENOEXEC, nullptr, 0);
> off_t dynsym_nameoff = sHdr->sh_offset;
>
> /* Locate symbol in the .dynsym section. */
> @@ -132,16 +143,16 @@ int elfLoadSymbol(void *dst, size_t size, void *map, size_t soSize,
> offset = dynsym->sh_offset + dynsym->sh_entsize * i;
> SymHeader *sym = elfPointer<SymHeader>(map, offset, soSize);
> if (!sym)
> - return -ENOEXEC;
> + return std::make_tuple(-ENOEXEC, nullptr, 0);
>
> offset = dynsym_nameoff + sym->st_name;
> char *name = elfPointer<char>(map, offset, soSize,
> strlen(symbol) + 1);
> if (!name)
> - return -ENOEXEC;
> + return std::make_tuple(-ENOEXEC, nullptr, 0);
>
> if (!strcmp(name, symbol) &&
> - sym->st_info & STB_GLOBAL && sym->st_size == size) {
> + sym->st_info & STB_GLOBAL) {
> targetSymbol = sym;
> break;
> }
> @@ -149,24 +160,22 @@ int elfLoadSymbol(void *dst, size_t size, void *map, size_t soSize,
>
> if (targetSymbol == nullptr) {
> LOG(IPAModule, Error) << "Symbol " << symbol << " not found";
> - return -ENOEXEC;
> + return std::make_tuple(-ENOEXEC, nullptr, 0);
> }
>
> /* Locate and return data of symbol. */
> if (targetSymbol->st_shndx >= eHdr->e_shnum)
> - return -ENOEXEC;
> + return std::make_tuple(-ENOEXEC, nullptr, 0);
> offset = eHdr->e_shoff + targetSymbol->st_shndx * eHdr->e_shentsize;
> sHdr = elfPointer<SecHeader>(map, offset, soSize);
> if (!sHdr)
> - return -ENOEXEC;
> + return std::make_tuple(-ENOEXEC, nullptr, 0);
> offset = sHdr->sh_offset + (targetSymbol->st_value - sHdr->sh_addr);
> - char *data = elfPointer<char>(map, offset, soSize, size);
> + char *data = elfPointer<char>(map, offset, soSize, targetSymbol->st_size);
> if (!data)
> - return -ENOEXEC;
> -
> - memcpy(dst, data, size);
> + return std::make_tuple(-ENOEXEC, nullptr, 0);
>
> - return 0;
> + return std::make_tuple(0, data, targetSymbol->st_size);
As the only error code that is returned is -ENOEXEC, would it make sense
to drop it and base the error check on the address being nullptr ? I
don't really mind either way, so with or without the change (but with
the include issue fixed),
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> }
>
> } /* namespace */
> @@ -257,8 +266,10 @@ int IPAModule::loadIPAModuleInfo()
> return ret;
> }
>
> - size_t soSize;
> + void *data;
> + size_t dataSize;
> void *map;
> + size_t soSize;
> struct stat st;
> int ret = fstat(fd, &st);
> if (ret < 0)
> @@ -275,11 +286,16 @@ int IPAModule::loadIPAModuleInfo()
> goto unmap;
>
> if (sizeof(unsigned long) == 4)
> - ret = elfLoadSymbol<Elf32_Ehdr, Elf32_Shdr, Elf32_Sym>
> - (&info_, sizeof(info_), map, soSize, "ipaModuleInfo");
> + std::tie(ret, data, dataSize) =
> + elfLoadSymbol<Elf32_Ehdr, Elf32_Shdr, Elf32_Sym>
> + (map, soSize, "ipaModuleInfo");
> else
> - ret = elfLoadSymbol<Elf64_Ehdr, Elf64_Shdr, Elf64_Sym>
> - (&info_, sizeof(info_), map, soSize, "ipaModuleInfo");
> + std::tie(ret, data, dataSize) =
> + elfLoadSymbol<Elf64_Ehdr, Elf64_Shdr, Elf64_Sym>
> + (map, soSize, "ipaModuleInfo");
> +
> + if (!ret && dataSize == sizeof(info_))
> + memcpy(&info_, data, dataSize);
>
> if (info_.moduleAPIVersion != IPA_MODULE_API_VERSION) {
> LOG(IPAModule, Error) << "IPA module API version mismatch";
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list