5

計算のためにエルフ画像のサイズを見つける必要があります。ヘッダーとセクションに関する情報を提供する Linux の readelf ユーティリティを試してみました。エルフの正確なファイルサイズ(全体)が必要です。

ヘッダー情報から ELF のサイズを確認するにはどうすればよいですか、またはイメージ全体を読み取らずに ELF のサイズを確認する方法はありますか。

4

6 に答える 6

6

特定の質問に対する答えは、ELF ファイルの場合は少しトリッキーです。

以下は、ヘッダーを使用して ELF ファイル内の「記述」情報のサイズを計算します: e_ehsize + (e_phnum * e_phentsize) + (e_shnum * e_shentsize)

上記は ELF ドキュメントに基づいています。

上記の合計に追加する次の要素は、セクション エントリのファイル内のサイズです。直感的に、ファイル内のセクションごとにsh_sizeを使用してこれを計算したいと思います (それらのセクションのe_shnum )。ただし、アライメントの問題により、これは正しい答えをもたらしません。sh_offset 値の順序付けられたリストを使用すると、セクション エントリが占める正確なバイト数を計算できます (sh_addralign の使用が必要なほど役に立たない奇妙な配置がいくつか見つかりました)。最後のセクション エントリには、セクション ヘッダー テーブルが最後であるため、ファイル ヘッダーのe_shoffを使用します。これは、私がチェックしたカップルで機能しました。

libelf の update.cには、elf ファイルを更新するときに使用する詳細が含まれています。

于 2012-02-22T23:54:01.973 に答える
4

例:

ls -l gives 126584

Calculation using the values also reported by readelf -h:

Start of section headers    e_shoff     124728
Size of section headers     e_shentsize 64
Number of section headers   e_shnum     29

e_shoff + ( e_shentsize * e_shnum ) = 126584

これは、セクション ヘッダー テーブル (SHT) が ELF の最後の部分であることを前提としています。これは通常のケースですが、最後のセクションが ELF の最後の部分である可能性もあります。これはチェックする必要がありますが、この例にはありません。

これはCでの実用的な実装で、次のようにコンパイルしgcc elfsize.c -o elfsizeます:

#include <elf.h>
#include <byteswap.h>
#include <stdio.h>
#include <stdint.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

typedef Elf32_Nhdr Elf_Nhdr;

static char *fname;
static Elf64_Ehdr ehdr;
static Elf64_Phdr *phdr;

#if __BYTE_ORDER == __LITTLE_ENDIAN
#define ELFDATANATIVE ELFDATA2LSB
#elif __BYTE_ORDER == __BIG_ENDIAN
#define ELFDATANATIVE ELFDATA2MSB
#else
#error "Unknown machine endian"
#endif

static uint16_t file16_to_cpu(uint16_t val)
{
    if (ehdr.e_ident[EI_DATA] != ELFDATANATIVE)
        val = bswap_16(val);
    return val;
}

static uint32_t file32_to_cpu(uint32_t val)
{
    if (ehdr.e_ident[EI_DATA] != ELFDATANATIVE)
        val = bswap_32(val);
    return val;
}

static uint64_t file64_to_cpu(uint64_t val)
{
    if (ehdr.e_ident[EI_DATA] != ELFDATANATIVE)
        val = bswap_64(val);
    return val;
}

static long unsigned int read_elf32(int fd)
{
    Elf32_Ehdr ehdr32;
    ssize_t ret, i;

    ret = pread(fd, &ehdr32, sizeof(ehdr32), 0);
    if (ret < 0 || (size_t)ret != sizeof(ehdr)) {
        fprintf(stderr, "Read of ELF header from %s failed: %s\n",
            fname, strerror(errno));
        exit(10);
    }

    ehdr.e_shoff        = file32_to_cpu(ehdr32.e_shoff);
    ehdr.e_shentsize    = file16_to_cpu(ehdr32.e_shentsize);
    ehdr.e_shnum        = file16_to_cpu(ehdr32.e_shnum);

    return(ehdr.e_shoff + (ehdr.e_shentsize * ehdr.e_shnum));
}

static long unsigned int read_elf64(int fd)
{
    Elf64_Ehdr ehdr64;
    ssize_t ret, i;

    ret = pread(fd, &ehdr64, sizeof(ehdr64), 0);
    if (ret < 0 || (size_t)ret != sizeof(ehdr)) {
        fprintf(stderr, "Read of ELF header from %s failed: %s\n",
            fname, strerror(errno));
        exit(10);
    }

    ehdr.e_shoff        = file64_to_cpu(ehdr64.e_shoff);
    ehdr.e_shentsize    = file16_to_cpu(ehdr64.e_shentsize);
    ehdr.e_shnum        = file16_to_cpu(ehdr64.e_shnum);

    return(ehdr.e_shoff + (ehdr.e_shentsize * ehdr.e_shnum));
}

long unsigned int get_elf_size(char *fname)
/* TODO, FIXME: This assumes that the section header table (SHT) is
the last part of the ELF. This is usually the case but
it could also be that the last section is the last part
of the ELF. This should be checked for.
*/
{
    ssize_t ret;
    int fd;
    long unsigned int size = 0;

    fd = open(fname, O_RDONLY);
    if (fd < 0) {
        fprintf(stderr, "Cannot open %s: %s\n",
            fname, strerror(errno));
        return(1);
    }
    ret = pread(fd, ehdr.e_ident, EI_NIDENT, 0);
    if (ret != EI_NIDENT) {
        fprintf(stderr, "Read of e_ident from %s failed: %s\n",
            fname, strerror(errno));
        return(1);
    }
    if ((ehdr.e_ident[EI_DATA] != ELFDATA2LSB) &&
        (ehdr.e_ident[EI_DATA] != ELFDATA2MSB))
    {
        fprintf(stderr, "Unkown ELF data order %u\n",
            ehdr.e_ident[EI_DATA]);
        return(1);
    }
    if(ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
        size = read_elf32(fd);
    } else if(ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
        size = read_elf64(fd);
    } else {
        fprintf(stderr, "Unknown ELF class %u\n", ehdr.e_ident[EI_CLASS]);
        return(1);
    }

    close(fd);
    return size;
}

int main(int argc, char **argv)
{
    ssize_t ret;
    int fd;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <ELF>\n", argv[0]);
        return 1;
    }
    fname = argv[1];

    long unsigned int size = get_elf_size(fname);
    fprintf(stderr, "Estimated ELF size on disk: %lu bytes \n", size);
    return 0;
}
于 2016-09-18T14:07:01.053 に答える
0

おそらくゲルフは役に立つかもしれません。

GElf は、ELF オブジェクト ファイルを操作するための、ELF クラスに依存しない汎用 API です。GElf は、32 ビットおよび 64 ビットの ELF 形式のオブジェクト ファイルを処理するための単一の共通インターフェイスを提供します。

特にこれらの機能:

elf32_fsize、elf64_fsize - オブジェクト ファイル タイプのサイズを返す

于 2010-06-08T07:29:17.263 に答える
0

gnu の「readelf」ユーティリティを試してみましたか?

http://sourceware.org/binutils/docs/binutils/readelf.html

于 2010-06-08T07:33:51.630 に答える
-2

stat関数ファミリ ( stat()lstat()、 ) を使用fstat()して、任意のファイルのサイズを取得できます (st_sizeメンバーのメンバーを使用stat)。もっと具体的なことが必要ですか?


本当に ELF 構造を使用したい場合は、その構造を含む elf.h ヘッダーを使用します。

typedef struct {
         unsigned char  e_ident[EI_NIDENT];
         uint16_t       e_type;
         uint16_t       e_machine;
         uint32_t       e_version;
         ElfN_Addr      e_entry;
         ElfN_Off       e_phoff;
         ElfN_Off       e_shoff;
         uint32_t       e_flags;
         uint16_t       e_ehsize;
         uint16_t       e_phentsize;
         uint16_t       e_phnum;
         uint16_t       e_shentsize;
         uint16_t       e_shnum;
         uint16_t       e_shstrndx;
 } Elf32_Ehdr;

これは ELF32 ファイルのヘッダーです (64 ビット ファイルの場合は 32 を 64 に置き換えます)。 e_ehsizeファイルのサイズ (バイト単位) です。


編集の提案として投稿されたコメントをそのままコピーします。

この答えは正しくありません。e_ehsize は、elf ファイルではなく、elf ヘッダーのサイズです。

于 2010-06-08T07:08:11.323 に答える