summaryrefslogtreecommitdiffstats
path: root/src/bld/linker.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/bld/linker.C')
-rw-r--r--src/bld/linker.C155
1 files changed, 155 insertions, 0 deletions
diff --git a/src/bld/linker.C b/src/bld/linker.C
new file mode 100644
index 000000000..59cbf6416
--- /dev/null
+++ b/src/bld/linker.C
@@ -0,0 +1,155 @@
+#include <stdint.h>
+#include <bfd.h>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+
+using std::cout;
+using std::endl;
+using std::string;
+using std::vector;
+
+struct Section
+{
+ string name;
+ size_t vma_offset;
+ size_t size;
+
+ bfd_byte* data;
+};
+
+struct Object
+{
+ public:
+ bfd* image;
+ Section text;
+ Section data;
+
+ bool read_object(char* file);
+ bool write_object(FILE* file);
+};
+
+vector<Object> objects;
+FILE* output;
+
+int main(int argc, char** argv)
+{
+ if (argc <= 2)
+ {
+ cout << argv[0] << " <output> <kernel> <modules>" << endl;
+ return -1;
+ }
+
+ // Open output file.
+ output = fopen(argv[1], "w+");
+ if (NULL == output)
+ {
+ int error = errno;
+ cout << "Error opening " << argv[1] << endl;
+ cout << strerror(error) << endl;
+ }
+
+ // Read input objects.
+ for (int files = 2; files < argc; files++)
+ {
+ Object o;
+ if (o.read_object(argv[files]))
+ {
+ objects.push_back(o);
+ }
+ }
+
+ for (vector<Object>::iterator i = objects.begin();
+ i != objects.end();
+ ++i)
+ {
+ i->write_object(output);
+ }
+ return 0;
+}
+
+bool Object::read_object(char* file)
+{
+ // Open BFD file.
+ image = bfd_openr(file, NULL);
+ if (!bfd_check_format(image, bfd_object))
+ {
+ cout << "Unsupported file format: " << file << endl;
+ return false;
+ }
+
+ cout << "File " << file << endl;
+
+ // Read sections.
+ bfd_section* image_section = image->sections;
+ while(image_section != NULL)
+ {
+ Section* s = NULL;
+ if (string(".text") == bfd_get_section_name(image, image_section))
+ {
+ s = &this->text;
+ }
+ if (string(".data") == bfd_get_section_name(image, image_section))
+ {
+ s = &this->data;
+ }
+ if (NULL != s)
+ {
+ s->name = bfd_get_section_name(image, image_section);
+ s->vma_offset = bfd_get_section_vma(image, image_section);
+ s->size = bfd_get_section_size(image_section);
+
+ bfd_malloc_and_get_section(image, image_section, &s->data);
+
+ cout << "Section " << s->name << endl;
+ cout << "\tSize " << std::dec << s->size << endl;
+ cout << "\tVMA " << std::hex << s->vma_offset << endl;
+ cout << "\tData " << std::hex << bfd_getb64(s->data)
+ << "..." << endl;
+ }
+
+ image_section = image_section->next;
+ }
+
+ cout << endl;
+
+ return true;
+}
+
+#define advance_to_page_align(f) \
+ { \
+ long pos = ftell(f); \
+ if (pos % 4096) \
+ { \
+ fseek((f), 4096 - (pos % 4096), SEEK_CUR); \
+ } \
+ }
+
+bool Object::write_object(FILE* file)
+{
+ // Start outputing object at page boundary.
+ advance_to_page_align(file);
+ long start_pos = ftell(file);
+
+ // Output TEXT section.
+ fseek(file, text.vma_offset, SEEK_CUR);
+ if (text.size != fwrite(text.data, 1, text.size, file))
+ {
+ int error = errno;
+ cout << "Error writing to output." << endl;
+ cout << strerror(error) << endl;
+ }
+
+ // Output DATA section.
+ fseek(file, start_pos + data.vma_offset, SEEK_SET);
+ if (data.size != fwrite(data.data, 1, data.size, file))
+ {
+ int error = errno;
+ cout << "Error writing to output." << endl;
+ cout << strerror(error) << endl;
+ }
+}
OpenPOWER on IntegriCloud