summaryrefslogtreecommitdiff
path: root/src/main.c
blob: 2c6268c6cd9e5a56ae0f1aba511fa60a59f9e219 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <stdio.h>
#include <stdlib.h>

#include <getopt.h>
#include <libelf/libelf.h>
#include <libelf/gelf.h>

#include <libelfu/libelfu.h>

#include "elfhandle.h"
#include "options.h"
#include "printing.h"


int main(int argc, char **argv)
{
  CLIOpts opts = { 0 };
  ELFHandles hIn = { 0 };
  ELFHandles hOut = { 0 };
  int exitval = EXIT_SUCCESS;
  ElfuElf *me;

  /* Is libelf alive and well? */
  if (elf_version(EV_CURRENT) == EV_NONE) {
    fprintf(stderr, "libelf init error: %s\n", elf_errmsg(-1));
  }


  /* Parse and validate user input */
  parseOptions(&opts, argc, argv);


  /* Open input/output files */
  openElf(&hIn, opts.fnInput, ELF_C_READ);
  if (!hIn.e) {
    exitval = EXIT_FAILURE;
    goto EXIT;
  }


  /* Now that we have a (hopefully) sane environment, execute commands.
   * Printing will have to be reimplemented based on the memory model.
   */
  if (opts.printHeader) {
    printHeader(hIn.e);
  }

  if (opts.printSegments) {
    printSegments(hIn.e);
  }

  if (opts.printSections) {
    printSections(hIn.e);
  }


  me = elfu_mFromElf(hIn.e);
  if (me) {
    closeElf(&hIn);
    printf("Model successfully loaded.\n");
    elfu_mCheck(me);
    printf("Input model checked.\n");
  } else {
    printf("Failed to load model, aborting.\n");
    goto EXIT;
  }


  /* Copy the input ELF to the output file if the latter is specified.
   * Perform requested transformations on the memory model on-the-fly. */
  if (!opts.fnOutput) {
    printf("No output file specified - no further operations performed.\n");
  } else {
    if (opts.expandNobitsOffs) {
      elfu_mExpandNobits(me, opts.expandNobitsOffs);
    }

    if (opts.insertBeforeSz) {
      elfu_mInsertSpaceBefore(me, opts.insertBeforeOffs, opts.insertBeforeSz);
    }

    if (opts.insertAfterSz) {
      elfu_mInsertSpaceAfter(me, opts.insertAfterOffs, opts.insertAfterSz);
    }

    if (opts.fnReladd) {
      ELFHandles hRel = { 0 };
      ElfuElf *mrel = NULL;

      openElf(&hRel, opts.fnReladd, ELF_C_READ);
      if (!hRel.e) {
        printf("--reladd: Failed to open file for --reladd, skipping operation.\n");
      } else {
        mrel = elfu_mFromElf(hRel.e);
        closeElf(&hRel);
        if (!me) {
          printf("--reladd: Failed to load model for --reladd, skipping operation.\n");
        } else {
          printf("--reladd: Model successfully loaded.\n");
          elfu_mCheck(mrel);
          printf("--reladd: Input model checked.\n");
          elfu_mReladd(me, mrel);
        }
      }

    }

    elfu_mCheck(me);
    printf("Output model checked.\n");


    openElf(&hOut, opts.fnOutput, ELF_C_WRITE);
    if (!hOut.e) {
      printf("Failed to open output file. Aborting.\n");
      exitval = EXIT_FAILURE;
      goto EXIT;
    }

    elfu_mToElf(me, hOut.e);
    printf("Model converted to ELF, ready to be written.\n");
  }



EXIT:
  if (hOut.e) {
    if (elf_update(hOut.e, ELF_C_WRITE) < 0) {
      fprintf(stderr, "elf_update() failed: %s\n", elf_errmsg(-1));
    }
    closeElf(&hOut);
  }

  if (hIn.e) {
    closeElf(&hIn);
  }

  return (exitval);
}