Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ld of data file makes size of data an *ABS* and not an integer

I have a c++ program which includes an external dependency on an empty xlsx file. To remove this dependency I converted this file to a binary object in view of linking it in directly, using:

ld -r -b binary -o template.o template.xlsx

followed by

objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents template.o template.o

Using objdump, I can see three variables declared :

$ objdump -x template.o

template.o:     file format elf64-x86-64
template.o
architecture: i386:x86-64, flags 0x00000010:
HAS_SYMS
start address 0x0000000000000000

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .rodata       00000fd1  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
SYMBOL TABLE:
0000000000000000 l    d  .rodata        0000000000000000 .rodata
0000000000000fd1 g       *ABS*  0000000000000000 _binary_template_xlsx_size
0000000000000000 g       .rodata        0000000000000000 _binary_template_xlsx_start
0000000000000fd1 g       .rodata        0000000000000000 _binary_template_xlsx_end

I then tell my program about this data :

template.h:
#ifndef TEMPLATE_H
#define TEMPLATE_H

#include <cstddef>
extern "C" {
  extern const char _binary_template_xlsx_start[];
  extern const char _binary_template_xlsx_end[];
  extern const int  _binary_template_xlsx_size;
}
#endif

This compiles and links fine,(although I am having some trouble automating it with cmake, see here : compile and add object file from binary with cmake)

However, when I use _binary_template_xlsx_size in my code, it is interpreted as a pointer to an address that doesn't exist. So to get the size of my data, I have to pass (int)&_binary_template_xlsx_size (or (int)(_binary_template_xlsx_end - _binary_template_xlsx_start))

Some research tells me that the *ABS* in the objdump above means "absolute value" but I don't get why. How can I get my c++ (or c) program to see the variable as an int and not as a pointer?

like image 375
Tom Macdonald Avatar asked Oct 21 '22 17:10

Tom Macdonald


1 Answers

An *ABS* symbol is an absolute address; it's more often created by passing --defsym foo=0x1234 to ld.

--defsym symbol=expression

Create a global symbol in the output file, containing the absolute address given by expression. [...]

Because an absolute symbol is a constant, it's not possible to link it into a C source file as a variable; all C object variables have an address, but a constant doesn't.

To make sure you don't dereference the address (i.e. read the variable) by accident, it's best to define it as const char [] as you have with the other symbols:

  extern const char _binary_template_xlsx_size[];

If you want to make sure you're using it as an int, you could use a macro:

  extern const char _abs_binary_template_xlsx_size[] asm("_binary_template_xlsx_size");
  #define _binary_template_xlsx_size ((int) (intptr_t) _abs_binary_template_xlsx_size)
like image 131
ecatmur Avatar answered Nov 02 '22 08:11

ecatmur