1

As stated in the question, is it possible to create a structure within a function, and then return that structure when the function exits? Since the structure is not created until the function is called, I don't know what to put in the prototype for the return value. Any advice/help would be great, thanks.

static void section_to_segment_map(Elf *elf, GElf_Ehdr *ehdr) {

    struct memory_data {
        int phdr_addrs[ehdr->e_phnum][2];
        int section_bounds[ehdr->e_shnum][2];
    } memData;

    for(int phead_cnt = 0; phead_cnt < ehdr->e_phnum; phead_cnt++) {
        GElf_Phdr mem;
        GElf_Phdr *phdr = gelf_getphdr(elf, phead_cnt, &mem);

        memData.phdr_addrs[phead_cnt][1] = phdr->p_vaddr;
        memData.phdr_addrs[phead_cnt][2] = phdr->p_vaddr + phdr->p_memsz;

    }
    printf("Starting and Ending Address Values for Program Segments:\n");
    for(int i = 0; i < ehdr->e_phnum; i++)
       printf("%x --> %x\n", memData.phdr_addrs[i][1], memData.phdr_addrs[i][2]);

    Elf_Scn *scn = NULL;
    for(int shead_cnt = 0; shead_cnt < ehdr->e_shnum; shead_cnt++) {
        scn = elf_getscn(elf, shead_cnt);
        GElf_Shdr shdr_mem;
        GElf_Shdr *shdr = gelf_getshdr(scn, &shdr_mem);

        memData.section_bounds[shead_cnt][1] = shdr->sh_addr;
        memData.section_bounds[shead_cnt][2] = shdr->sh_addr + shdr->sh_size;
    }
    printf("\n");
    printf("Starting and Ending Addresses for Program Sections:\n");
    for(int j = 0; j < ehdr->e_shnum; j++) 
        printf("%x --> %x\n", memData.section_bounds[j][1], memData.section_bounds[j][2]);

    return memData;
}
nice_remark
  • 325
  • 3
  • 12
  • 3
    Why would you want to do this? How would a consumer of you code declare a variable on the struct? – Sean Dec 13 '17 at 16:38
  • 1
    Need to return the two arrays for future usage within the program. – nice_remark Dec 13 '17 at 16:42
  • 1
    You could declare the struct outside the function, or pass pointers or refs as arguments so that the function can modify the data of the handle passed in – idontseethepoint Dec 13 '17 at 16:44
  • 1
    Just declare the structure outside the function. It'll be easier, and it's what people expect. – Sean Dec 13 '17 at 16:47
  • Array indices start at 0, not 1. – Ian Abbott Dec 13 '17 at 17:56
  • 1
    You can return a value of structure type from a function, but the return type needs to be completely declared before the function declaration. Currently, your `struct memory_data` type is only completely declared within the function, so you cannot return it. – Ian Abbott Dec 13 '17 at 17:59
  • Anyways, if you want to return something from a function, don't use `void` as its return type in the declaration. – Bob__ Dec 13 '17 at 18:02
  • "create a structure within a function, and then return that structure when the function exits?" No – chux - Reinstate Monica Dec 13 '17 at 18:22
  • @Sean [declare the structure outside the function](https://stackoverflow.com/questions/47798086/return-a-structure-that-was-created-within-a-function#comment82557362_47798086) will not work at file scope as the members have variable size. – chux - Reinstate Monica Dec 13 '17 at 18:28

2 Answers2

1

Return a structure that was created within a function?
is it possible to create a structure within a function, and then return that structure ..?

No. The return type must be defined before the function body.

// void section_to_segment_map(Elf *elf, GElf_Ehdr *ehdr) {
struct memory_data section_to_segment_map(Elf *elf, GElf_Ehdr *ehdr) {

Yet OP's struct has a variable size and so defining the struct ahead of time fails.

struct memory_data {
    // fails  "error: variably modified 'phdr_addrs' at file scope"
    int phdr_addrs[some_variable][2];  
    ...
} memData;

A fixed sized struct would work, yet may be inefficient if large.

#define MEMORY_DATA_N_MAX 10
struct memory_data {
    int phdr_addrs[MEMORY_DATA_N_MAX][2];  
    ...
} memData;

Various dynamic options exist such as creating a struct that contains the size information and pointers to allocated space. This obliges section_to_segment_map() to allocate memory and the caller to insure it is free'd.

struct memory_data {
    size_t sz;
    int (*phdr_addrs)[2];
    int (*section_bounds)[2];
} memData;

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

First of all, in order to return a structure from you function you need to declare it outside of the functions scope, so other functions would be able to use it as well.

/* You can change this size if you wish */
#define PHDR_ADDRESS_SIZE (0xffff)
struct memory_data {

        int phdr_addrs[PHDR_ADDRESS_SIZE][2];
        int section_bounds[PHDR_ADDRESS_SIZE][2];
   } memData;

static void section_to_segment_map(Elf *elf, GElf_Ehdr *ehdr)
{
/* Code... */
}

int main(void)
{
    memData m = {};
}

In order to return a structure from your function, you have two main options.

Actually return the structre

You need to cahnge the return value of the function to be from the type "memData" instead of "void". Then, you can just return that value. For example:

memData section_to_segment_map(Elf *elf, GElf_Ehdr *ehdr)
{
    memData m = {};
    /* Code... */
    return m;
}

Pass an out parameter to the function

Another option, which is more reccomended in my opinion is to pass an out parameter to the function, which is a pointer.

You need to pass a pointer to memData, and the you can change it inside your function. For example:

void section_to_segment_map(Elf *elf, GElf_Ehdr *ehdr, memData* m)
{
    for(int phead_cnt = 0; phead_cnt < ehdr->e_phnum; phead_cnt++) {
        GElf_Phdr mem;
        GElf_Phdr *phdr = gelf_getphdr(elf, phead_cnt, &mem);

        *memData.phdr_addrs[phead_cnt][1] = phdr->p_vaddr;
        *memData.phdr_addrs[phead_cnt][2] = phdr->p_vaddr + phdr->p_memsz;
    }
    /* More of the code.... */
return;
}

In order to call the function from main, you should do the following:

int main(void)
{
    memData m = {};
    /* Put your own arguments isntead of <elf>, <edhr> */
    section_to_segment_map(<elf>, <ehdr>, &m);

}
Idan
  • 333
  • 2
  • 8
  • Read the following: https://stackoverflow.com/questions/13645936/variably-modified-array-at-file-scope-in-c. Anyway, i have edited the answer. – Idan Dec 13 '17 at 18:27
  • `*memData.phdr_addrs[phead_cnt][1]` is trying to dereference an `int`. Perhaps you meant `memData->phdr_addrs[phead_cnt][1]`. Also the indices should be 0 and 1, not 1 and 2 (this error is also in the original code). – Ian Abbott Dec 13 '17 at 18:34
  • You probably missed a `typedef` in the first snippet. – Bob__ Dec 13 '17 at 19:08
  • @IanAbbott perhaps they meant `m->phdr_addrs[phead_cnt][1]`, given that `memData` *should* be the type of the argument `m`. – Bob__ Dec 13 '17 at 19:15
  • @Bob__ Yes, I was thinking memData was the pointer variable for some reason (probably end of day tiredness!). – Ian Abbott Dec 14 '17 at 10:26