ufoaiorg / ufoai

UFO:Alien Invasion
http://ufoai.org
GNU General Public License v2.0
148 stars 51 forks source link

BFD API changed with binutils 2.34 #50

Closed FalcoGer closed 4 years ago

FalcoGer commented 4 years ago

Compile fails with the latest version of binutils.

src/shared/bfd.cpp: In function ‘void lookup_section(bfd*, asection*, void*)’:
src/shared/bfd.cpp:61:8: error: ‘bfd_get_section_flags’ was not declared in this scope; did you mean ‘bfd_set_section_flags’?
   61 |  if (!(bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
      |        ^~~~~~~~~~~~~~~~~~~~~
      |        bfd_set_section_flags
src/shared/bfd.cpp:64:22: error: ‘bfd_get_section_vma’ was not declared in this scope; did you mean ‘bfd_set_section_vma’?
   64 |  const bfd_vma vma = bfd_get_section_vma(abfd, sec);
      |                      ^~~~~~~~~~~~~~~~~~~
      |                      bfd_set_section_vma
src/shared/bfd.cpp:65:35: error: ‘bfd_get_section_size’ was not declared in this scope; did you mean ‘bfd_set_section_size’?
   65 |  if (data->counter < vma || vma + bfd_get_section_size(sec) <= data->counter)
      |                                   ^~~~~~~~~~~~~~~~~~~~
      |                                   bfd_set_section_size
===> CXX [testall] src/shared/utf8.cpp
make: *** [Makefile:183: debug-linux-x86_64/testall/shared/bfd.cpp.o] Error 1

The solution is to change the function calls like so:

/**
 * @file
 * @brief Stacktrace functions (libbfd/binutils)
 */

/*
All original material Copyright (C) 2002-2020 UFO: Alien Invasion.

Copyright (C) 1997-2001 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#include "../common/common.h"

#ifdef HAVE_BFD_H
#include "bfd.h"

void output_init (struct output_buffer* ob, char*  buf, size_t sz)
{
    ob->buf = buf;
    ob->sz = sz;
    ob->ptr = 0;
    ob->buf[0] = '\0';
}

void output_print (struct output_buffer* ob, const char*  format, ...)
{
    va_list ap;
    if (ob->sz == ob->ptr)
        return;
    ob->buf[ob->ptr] = '\0';
    va_start(ap, format);
    vsnprintf(ob->buf + ob->ptr, ob->sz - ob->ptr, format, ap);
    va_end(ap);

    ob->ptr = strlen(ob->buf + ob->ptr) + ob->ptr;
}

static void lookup_section (bfd* abfd, asection* sec, void* opaque_data)
{
    struct find_info* data = (struct find_info*)opaque_data;

    if (data->func)
        return;

    if (!(bfd_section_flags(sec) & SEC_ALLOC))
        return;

    const bfd_vma vma = bfd_section_vma(sec);
    if (data->counter < vma || vma + bfd_section_size(sec) <= data->counter)
        return;

    bfd_find_nearest_line(abfd, sec, data->symbol, data->counter - vma,
            &(data->file), &(data->func), &(data->line));
}

void find (struct bfd_ctx * b, size_t offset, const char** file, const char** func, unsigned* line)
{
    struct find_info data;
    data.func = nullptr;
    data.symbol = b->symbol;
    data.counter = offset;
    data.file = nullptr;
    data.func = nullptr;
    data.line = 0;

    bfd_map_over_sections(b->handle, &lookup_section, &data);
    if (file) {
        *file = data.file;
    }
    if (func) {
        *func = data.func;
    }
    if (line) {
        *line = data.line;
    }
}

static void list_matching_formats (struct output_buffer* ob, const char*  procname, char** p)
{
    if (!p || !*p)
        return;

    output_print(ob, "%s: Matching formats: ", procname);
    while (*p)
        output_print(ob, " %s", *p++);
    output_print(ob, "\n");
}

static int init_bfd_ctx (struct bfd_ctx* bc, const char*  procname, struct output_buffer* ob)
{
    void* symbol_table;
    unsigned dummy = 0;
    char** matching = nullptr;

    bc->handle = nullptr;
    bc->symbol = nullptr;

    bfd* b = bfd_openr(procname, 0);
    if (!b) {
        output_print(ob, "Failed to open bfd from (%s)\n", procname);
        return 1;
    }

    if (bfd_check_format(b, bfd_archive)) {
        output_print(ob, "Cannot get addresses from archive (%s)\n", b->filename);
        bfd_close(b);
        return -1;
    }

    if (!bfd_check_format_matches(b, bfd_object, &matching)) {
        const char* errmsg = bfd_errmsg(bfd_get_error());
        output_print(ob, "%s (%s)\n", errmsg, b->filename);
        if (bfd_get_error() == bfd_error_file_ambiguously_recognized) {
            list_matching_formats(ob, b->filename, matching);
            free(matching);
        }
        bfd_close(b);
        return -1;
    }

    if ((bfd_get_file_flags(b) & HAS_SYMS) == 0) {
        const char* errmsg = bfd_errmsg(bfd_get_error());
        output_print(ob, "Failed to get file flags from (%s) %s\n", b->filename, errmsg);
        bfd_close(b);
        return 1;
    }

    if (bfd_read_minisymbols(b, FALSE, &symbol_table, &dummy) == 0) {
        if (bfd_read_minisymbols(b, TRUE, &symbol_table, &dummy) < 0) {
            const char* errmsg = bfd_errmsg(bfd_get_error());
            output_print(ob, "Failed to read symbols from (%s): %s\n", b->filename, errmsg);
            free(symbol_table);
            bfd_close(b);
            return 1;
        }
    }

    bc->handle = b;
    bc->symbol = (asymbol**)symbol_table;

    return 0;
}

static void close_bfd_ctx (struct bfd_ctx* bc)
{
    free(bc->symbol);
    if (bc->handle) {
        bfd_close(bc->handle);
    }
}

struct bfd_ctx* get_bc (struct output_buffer* ob, struct bfd_set* set, const char* procname)
{
    struct bfd_ctx bc;

    while (set->name) {
        if (Q_streq(set->name, procname)) {
            return set->bc;
        }
        set = set->next;
    }
    if (init_bfd_ctx(&bc, procname, ob)) {
        return nullptr;
    }
    set->next = (bfd_set*)calloc(1, sizeof(*set));
    set->bc = (bfd_ctx*)malloc(sizeof(struct bfd_ctx));
    memcpy(set->bc, &bc, sizeof(bc));
    set->name = strdup(procname);

    return set->bc;
}

void release_set (struct bfd_set* set)
{
    while (set->next) {
        struct bfd_set* temp = set->next;
        free(set->name);
        close_bfd_ctx(set->bc);
        free(set);
        set = temp;
    }
}

#endif

Obviously this should be generated in the configure stage, depending on the API version. But I have no idea how configure/make works.

geever commented 4 years ago

This has been fixed in the main repo on SourceForge. commit id: a542a87a891f96b1ab2c44d35b2f6f16859a5019

FalcoGer commented 4 years ago

This has been fixed in the main repo on SourceForge. commit id: a542a87a891f96b1ab2c44d35b2f6f16859a5019

What do you mean main repo? ufoai.org clearly links to github. Why isn't this repo (on github) up to date? I didn't even know sourceforge used source control. How do I pull from there?

geever commented 4 years ago

https://ufoai.org/wiki/Getting_the_source

SF was always the primary source. Github is a mirror of ours. Unfortunately, it seems the transfer service broke when ufoai.org server was rebuilt, I'll look into that.