Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > alt.os.development > #9549 > unrolled thread

Questions about the Implementation of the ELF format

Started by"Isaac D. Cohen" <8switchsoftware@gmail.com>
First post2016-05-23 22:07 -0700
Last post2016-05-25 22:18 -0700
Articles 20 on this page of 23 — 6 participants

Back to article view | Back to alt.os.development


Contents

  Questions about the Implementation of the ELF format "Isaac D. Cohen" <8switchsoftware@gmail.com> - 2016-05-23 22:07 -0700
    Re: Questions about the Implementation of the ELF format Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-05-24 03:48 -0400
    Questions about the Implementation of the ELF format Peter Cheung <mcheung63@gmail.com> - 2016-05-24 01:10 -0700
    Re: Questions about the Implementation of the ELF format "Alexei A. Frounze" <alexfrunews@gmail.com> - 2016-05-24 01:18 -0700
    Re: Questions about the Implementation of the ELF format "Mike Gonta" <mikegonta@gmail.com> - 2016-05-24 10:34 -0400
    Re: Questions about the Implementation of the ELF format Herbert Kleebauer <klee@unibwm.de> - 2016-05-24 17:24 +0200
    Re: Questions about the Implementation of the ELF format "Isaac D. Cohen" <8switchsoftware@gmail.com> - 2016-05-24 14:18 -0700
      Re: Questions about the Implementation of the ELF format "Alexei A. Frounze" <alexfrunews@gmail.com> - 2016-05-25 02:21 -0700
    Re: Questions about the Implementation of the ELF format "Isaac D. Cohen" <8switchsoftware@gmail.com> - 2016-05-25 15:02 -0700
      Re: Questions about the Implementation of the ELF format "Mike Gonta" <mikegonta@gmail.com> - 2016-05-25 19:03 -0400
        Re: Questions about the Implementation of the ELF format "Isaac D. Cohen" <8switchsoftware@gmail.com> - 2016-05-26 14:51 -0700
          Re: Questions about the Implementation of the ELF format Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-05-27 02:55 -0400
            Re: Questions about the Implementation of the ELF format "Isaac D. Cohen" <8switchsoftware@gmail.com> - 2016-05-27 13:43 -0700
              Re: Questions about the Implementation of the ELF format "Mike Gonta" <mikegonta@gmail.com> - 2016-05-27 17:40 -0400
                Re: Questions about the Implementation of the ELF format "Isaac D. Cohen" <8switchsoftware@gmail.com> - 2016-05-28 20:15 -0700
                  Re: Questions about the Implementation of the ELF format Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-05-29 02:35 -0400
                    Re: Questions about the Implementation of the ELF format "Isaac D. Cohen" <8switchsoftware@gmail.com> - 2016-06-15 13:51 -0700
          Re: Questions about the Implementation of the ELF format Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-05-27 03:09 -0400
          Re: Questions about the Implementation of the ELF format "Alexei A. Frounze" <alexfrunews@gmail.com> - 2016-05-27 00:10 -0700
          Re: Questions about the Implementation of the ELF format Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-06-02 16:25 -0400
        Re: Questions about the Implementation of the ELF format Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-05-27 02:38 -0400
          Re: Questions about the Implementation of the ELF format "Mike Gonta" <mikegonta@gmail.com> - 2016-05-27 04:11 -0400
      Re: Questions about the Implementation of the ELF format "Alexei A. Frounze" <alexfrunews@gmail.com> - 2016-05-25 22:18 -0700

Page 1 of 2  [1] 2  Next page →


#9549 — Questions about the Implementation of the ELF format

From"Isaac D. Cohen" <8switchsoftware@gmail.com>
Date2016-05-23 22:07 -0700
SubjectQuestions about the Implementation of the ELF format
Message-ID<06b38764-b3ee-4eed-9b82-f62c1d68b0ec@googlegroups.com>
Hi,

While what I’m about to write may at first seem off topic, it can somehow have something to do with OS Development. If anyone knows of a newsgroup in which this would be more on topic, please let me know.

In any case, I’m trying to figure out how to include C/C++ in my operating system. So I googled around and found that I have to cross-compile the C/C++ file into some kind of format, for example ELF. So my first question is, why? Why can’t the compiler just generate plain binary files?

Anyway, I quickly realized that I’m going to have to learn all about ELFs, because otherwise, I won’t know how to jump into the executable from an assembly file in my OS. So I got the ELF specification (from here: http://flint.cs.yale.edu/cs422/doc/ELF_Format.pdf), and began reading it. Also, I thought it would be helpful to look at an ELF executable as I read the specification and follow along. So for example, if the specification says that an ELF file begins with 0x7F followed by the ASCII characters ‘E’, ‘L’ and ‘F’, I would take a look at the beginning of the ELF file and see if it has the 0x7F ‘ELF’. So I opened a 64-bit ELF executable compiled for Linux, in Bless Hex Editor and began to follow along. It did not take long until I noticed that the program does not appear to be following the specification.

Here is what happened. The specification says that the first 16 bytes make up the “ELF Identification” and then there is a two byte field indicating what type of ELF file it is. The program I was looking at had a 2 in this field meaning it is an executable. So far so good. The specification also states that executables must have a Program Header Table.

Later on, the specification says that at offset 28 there is a 4 byte field containing the offset (from the beginning of the file) of the Program Header Table. “If the file has no program header table, this member holds zero.” the specification says. However, in the program I was looking at, this field seems to contain a zero despite the program being an executable. How can that be?

Also the specification says that files that don’t have a program header table must have a section header table and vise versa. So in that case, the ELF I was looking at, should at least have a section header table. But to my surprise, the fields in the ELF header that should contain the length of each section header in the table and the amount of entries in the section header table both contain zeros! How can that be? Especially when the field that is supposed to contain the offset of the section header table (from the beginning of the file), contains 64, meaning that the section header table with 0 entries that are 0 bytes each, is at offset 64 from the beginning of the file. How is this possible?


Thank you very much,
Isaac D. Cohen

[toc] | [next] | [standalone]


#9550

FromRod Pemberton <NoHaveNotOne@bcczxcfre.cmm>
Date2016-05-24 03:48 -0400
Message-ID<20160524034801.357f351a@_>
In reply to#9549
On Mon, 23 May 2016 22:07:38 -0700 (PDT)
"Isaac D. Cohen" <8switchsoftware@gmail.com> wrote:

> In any case, I’m trying to figure out how to include C/C++ in my
> operating system.

1) in-lined assembly in C
2) link assembly object with C object

I tend to prefer #1 since you only need a few special instructions and
maybe one or two routines in assembly for an OS.  Everything else can
be done in C.  Having most of the code in C reduces compiler dependence
if you're using multiple C compilers.

Others tend to like the convenience of using an assembler of their
choice and linking the assembly with C, e.g. GCC C compiler with NASM
assembler instead of GNU AS (GAS).

Notice that I didn't mention C++.  My understanding is that if you use
C++ code in an OS that you must provide your own routines for "new" and
"delete" since C++ code frequently calls these.  If this is actually an
issue with C++, i.e., if the C++ code is not independent of them, then
you'll most likely know when you try to link the C++ code as
stand-alone code, i.e., missing new and delete functions, or it may
crash when executed.

I would stick with C or assembly for OS development.  I just happen to
find assembly to be more tedious, but some people, like Wolfgang,
perhaps Mike Gonta, have had excellent results with an assembly only
approach.  Many of the people who have posted here over many years seem
to develop from Linux using C.  I'm one of the rare ones to develop
from DOS using redundant C compilers.

The advantage of developing from DOS is that there isn't a protected OS
blocking you from running code that directly programs the hardware.
So, you can develop and test your OS code in DOS without having to boot
or re-boot your OS repeatedly.  You also don't have the issue of
incorrect emulation of various emulators.  E.g., I developed my mouse
driver, keyboard driver, and video driver, code to initialize and
reprogram PICs, RTC, video registers, mouse, keyboard, etc and even OS
setup such as GDT etc, all while running DOS.  After the code was
working, I merged the code into my OS.

> So I googled around and found that I have to cross-compile the
> C/C++ file into some kind of format, for example ELF. 

Um ...

Generally, C compilers have certain native formats which are needed by
the host OS.  E.g., Linux may only support a few flavors of ELF, e.g.,
32-bit and 64-bit, while an old DOS C compiler, like Watcom or
OpenWatcom may support a half-dozen formats, since many formats were
used for different reasons with DOS, historically.  So, you have no
choice but to produce code for the intended format(s) that can be used
by the OS, but C compilers can usually produce both executable and
object files.  The latter are linked together to create an executable
file.

> So my first question is, why? Why can’t the compiler just
> generate plain binary files?

So, I think the base answer is that compilers produce output that the
host OS can use, i.e., execute, otherwise they don't.  I.e., the file
must be executable by the OS, or linkable by the compiler into an
executable for that OS to be of use.  Sometimes C compilers have
utilities to strip the stub or header off of an executable or object
file.

AFAIK, 32-bit DOS C compilers, Linux C compilers, and Windows C
compilers can only produce executable and object formats.  However,
16-bit DOS C compilers can produce plain binary, since DOS can execute
16-bit .com files which are plain binary.  As an aside, it's also a
security risk to be able to execute raw code.  The OS isn't really able
to perform any safety checks or relocation of the code without a header.

Certain C compilers, like GCC for Linux, have switches needed to
produce stand-alone OS images, since said compilers are used to produce
the host OS.  Other C compilers, e.g., Windows or DOS, aren't used to
produce the host OS.  So, there is no need for them to have such
functionality.  If they could, it would be a major security concern.
E.g., imagine if you could modify, re-compile, and re-install Windows
10 yourself, or someone else could ...

Some C compilers have switches which will reduce or eliminate dependence
on the host's OS calls, but that has nothing to do with the object or
executable format.  That just makes sure your OS doesn't call an
external C library or CRT start-up code, which is half the problem of
producing stand-alone code for the OS.  The other half is getting the
code into a bootable format, e.g., ELF, COFF, Multiboot compliant, DOS
OMF, etc.

> Anyway, I quickly realized that I’m going to have to learn all about
> ELFs, because otherwise, I won’t know how to jump into the executable
> from an assembly file in my OS. So I got the ELF specification (from
> here: http://flint.cs.yale.edu/cs422/doc/ELF_Format.pdf), and began
> reading it.

Chris Giese ELF format summary
http://geezer.osdevbrasil.net/osd/exec/elf.txt

> Also, I thought it would be helpful to look at an ELF
> executable as I read the specification and follow along. So for
> example, if the specification says that an ELF file begins with 0x7F
> followed by the ASCII characters ‘E’, ‘L’ and ‘F’, I would take a
> look at the beginning of the ELF file and see if it has the 0x7F
> ‘ELF’. So I opened a 64-bit ELF executable compiled for Linux, in
> Bless Hex Editor and began to follow along. It did not take long
> until I noticed that the program does not appear to be following the
> specification.

...

> [ELF questions]

I'm not familiar with the ELF format.  I know that GRUB and GRUB4DOS
should load ELF format OSes.

I know that some executable formats also have an object format of the
same name, e.g., COFF has both COFF executables and COFF objects.
I.e., make sure you're looking at the correct data.


Rod Pemberton

[toc] | [prev] | [next] | [standalone]


#9551

FromPeter Cheung <mcheung63@gmail.com>
Date2016-05-24 01:10 -0700
Message-ID<41cbd0a0-6c72-41a8-801c-23043fbdac5c@googlegroups.com>
In reply to#9549
elf can do dynamic linking

[toc] | [prev] | [next] | [standalone]


#9552

From"Alexei A. Frounze" <alexfrunews@gmail.com>
Date2016-05-24 01:18 -0700
Message-ID<dfad6e5e-dc6e-4e40-94a6-64d0ebb864ab@googlegroups.com>
In reply to#9549
On Monday, May 23, 2016 at 10:07:40 PM UTC-7, Isaac D. Cohen wrote:
> In any case, I’m trying to figure out how to include C/C++ in my operating system. So I googled around and found that I have to cross-compile the C/C++ file into some kind of format, for example ELF. So my first question is, why? Why can’t the compiler just generate plain binary files?
> 

Because plain binary files cannot easily include additional
information supporting various useful features (relocation,
code vs data distinguishing, stack unwinding on exceptions,
debug/symbol info, DLLs, embedded data files, etc etc).

> Anyway, I quickly realized that I’m going to have to learn all about ELFs, because otherwise, I won’t know how to jump into the executable from an assembly file in my OS. So I got the ELF specification (from here: http://flint.cs.yale.edu/cs422/doc/ELF_Format.pdf), and began reading it. Also, I thought it would be helpful to look at an ELF executable as I read the specification and follow along. So for example, if the specification says that an ELF file begins with 0x7F followed by the ASCII characters ‘E’, ‘L’ and ‘F’, I would take a look at the beginning of the ELF file and see if it has the 0x7F ‘ELF’. So I opened a 64-bit ELF executable compiled for Linux, in Bless Hex Editor and began to follow along. It did not take long until I noticed that the program does not appear to be following the specification.
> 

What does objdump tell you about your file? What headers,
sections and other things does it find in the file?

objdump -x file

Alex

[toc] | [prev] | [next] | [standalone]


#9553

From"Mike Gonta" <mikegonta@gmail.com>
Date2016-05-24 10:34 -0400
Message-ID<ni1op3$1ndv$1@gioia.aioe.org>
In reply to#9549
"Isaac D. Cohen" wrote:
> I’m trying to figure out how to include C/C++ in my
> operating system. So I googled around and found that I
> have to cross-compile the C/C++ file into some kind of
> format, for example ELF. So my first question is, why? Why
> can’t the compiler just generate plain binary files?

If you want to use GCC on Windows - that's the way it is.

> Anyway, I quickly realized that I’m going to have to learn
> all about ELFs, ....

No need to if you're going to generate a flat binary file.
Simple link the object files and specify:

OUTPUT_FORMAT("binary")

in the linker file.

> because otherwise, I won’t know how to jump into the
> executable from an assembly file in my OS.

Simply link with the asm object file and include a jmp or
call to the function name used in the "C" file.
Another simple technique to use when running a loaded flat
binary from the OS is to call the beginning address of the
loaded file. In this case since you can never be sure of
where the actually address of the "main" function will be in
the actual binary simply put an inline asm statement at the
end of a "#include"d file:

  __asm__ ("jmp main");

and the linker will take care of the rest.
Also, for example, if you load the the file to (for example)
0x400000, you can call it from "C" in the OS loader with:

  ((int (*)(void ))0x400000)();

(with the appropriate return type and parameters).


Mike Gonta
look and see - many look but few see

http://mikegonta.com
http://tawk.to/mikegonta

[toc] | [prev] | [next] | [standalone]


#9554

FromHerbert Kleebauer <klee@unibwm.de>
Date2016-05-24 17:24 +0200
Message-ID<ni1roj$1sp6$1@gioia.aioe.org>
In reply to#9549
On 24.05.2016 07:07, Isaac D. Cohen wrote:

> In any case, I’m trying to figure out how to include C/C++ in 
> my operating system. So I googled around and found that I have
> to cross-compile the C/C++ file into some kind of format, for
> example ELF. So my first question is, why? Why can’t the
> compiler just generate plain binary files?

> Anyway, I quickly realized that I’m going to have to learn all 
> about ELFs, because otherwise, I won’t know how to jump into
> the executable from an assembly file in my OS.

If you already have a working system on your OS which let
you compile and run assembly programs, then cross compile C
code not to binary but to assembly source code, transfer it
to your OS and then use the assembler in your OS.

[toc] | [prev] | [next] | [standalone]


#9557

From"Isaac D. Cohen" <8switchsoftware@gmail.com>
Date2016-05-24 14:18 -0700
Message-ID<3098f645-49d7-4d3d-9bf3-75ba43a5ddde@googlegroups.com>
In reply to#9549
Rod Pemberton Wrote:

> The OS isn't really able to perform any safety checks or relocation of
> the code without a header.

Alexei A. Frounze wrote:

> Because plain binary files cannot easily include additional 
> information supporting various useful features (relocation, 
> code vs data distinguishing, stack unwinding on exceptions, 
> debug/symbol info, DLLs, embedded data files, etc etc). 

I don't quite understand this whole thing about relocation. I thought the whole
reason the phenomenon of paging exists is because it solves the relocation
problem by creating a virtual address space for each process and that the only
code that still has a relocation problem are the shared libraries which is why
they are compiled as position independent code. But what is this about relocation
with regular executables?

> What does objdump tell you about your file? What headers, 
> sections and other things does it find in the file? 

Hmmm. That's a good idea. Let's see...
 
a.out:     file format elf64-x86-64
a.out
architecture: i386:x86-64, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x0000000000400430

Program Header:
    PHDR off    0x0000000000000040 vaddr 0x0000000000400040 paddr 0x0000000000400040 align 2**3
         filesz 0x00000000000001f8 memsz 0x00000000000001f8 flags r-x
  INTERP off    0x0000000000000238 vaddr 0x0000000000400238 paddr 0x0000000000400238 align 2**0
         filesz 0x000000000000001c memsz 0x000000000000001c flags r--
    LOAD off    0x0000000000000000 vaddr 0x0000000000400000 paddr 0x0000000000400000 align 2**21
         filesz 0x00000000000006f4 memsz 0x00000000000006f4 flags r-x
    LOAD off    0x0000000000000e10 vaddr 0x0000000000600e10 paddr 0x0000000000600e10 align 2**21
         filesz 0x0000000000000228 memsz 0x0000000000000230 flags rw-
 DYNAMIC off    0x0000000000000e28 vaddr 0x0000000000600e28 paddr 0x0000000000600e28 align 2**3
         filesz 0x00000000000001d0 memsz 0x00000000000001d0 flags rw-
    NOTE off    0x0000000000000254 vaddr 0x0000000000400254 paddr 0x0000000000400254 align 2**2
         filesz 0x0000000000000044 memsz 0x0000000000000044 flags r--
EH_FRAME off    0x00000000000005cc vaddr 0x00000000004005cc paddr 0x00000000004005cc align 2**2
         filesz 0x0000000000000034 memsz 0x0000000000000034 flags r--
   STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
         filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
   RELRO off    0x0000000000000e10 vaddr 0x0000000000600e10 paddr 0x0000000000600e10 align 2**0
         filesz 0x00000000000001f0 memsz 0x00000000000001f0 flags r--

This is not the entire output, but it's probably the most important part of it as
it shows that the ELF indeed does have a program header. Notice that according
this output the offset of the program header table is 0x40. When I open the file
with Bless Hex Editor 0x40 is the offset of the Section Header Table. The offset
of the program header table, according to what I see in Bless, is 0x0 meaning it
doesn't exist.

But how is it possible that objdump and I are reading a file differently? What
does objdump see in the file that tells it that there is a program header even
though when I read the file it seems otherwise?

Thank you very much,
Isaac D. Cohen

[toc] | [prev] | [next] | [standalone]


#9560

From"Alexei A. Frounze" <alexfrunews@gmail.com>
Date2016-05-25 02:21 -0700
Message-ID<a74a8fff-76f2-40c3-ba3f-2cdaeadb2e98@googlegroups.com>
In reply to#9557
On Tuesday, May 24, 2016 at 2:18:08 PM UTC-7, Isaac D. Cohen wrote:
> I don't quite understand this whole thing about relocation. I thought the whole
> reason the phenomenon of paging exists is because it solves the relocation
> problem by creating a virtual address space for each process and that the only
> code that still has a relocation problem are the shared libraries which is why
> they are compiled as position independent code. But what is this about relocation
> with regular executables?

Paging exists to fool big fat programs into believing they have
lots of fast and expensive RAM to use when in fact most of it
is backed by your cheap and slow disk storage. Virtual memory
it is.

Position-independent code is a good thing, but it's not always
cheap (the CPU simply may have no decent PC-relative addressing)
and it itself may need a tiny bit of relocation.

Let's say you have this tiny bit of C code:

#include <stdio.h>

int a = 123;
int* pa = &a;

int main(void)
{
  printf("%d\n", *pa);
  return 0;
}

On the x86, direct calls are PC-relative, so calling printf()
may be deemed covered in terms of position independence.
But data accesses to pa and a in non-64-bit modes are not
PC-relative. Hence relocations and/or complex indirection
schemes.

OTOH, in the 64-bit mode you can access both pa and a relative
to PC. However, how does pa get its initial value, the address
of a? There must be some code somewhere that takes the address
of a and stores it in memory at the address of pa. That is a form
of relocation. Bummer!

Alex

[toc] | [prev] | [next] | [standalone]


#9564

From"Isaac D. Cohen" <8switchsoftware@gmail.com>
Date2016-05-25 15:02 -0700
Message-ID<ba3e35ec-d8f7-4d00-940b-e04c1ba1d581@googlegroups.com>
In reply to#9549
> Paging exists to fool big fat programs into believing they have 
> lots of fast and expensive RAM to use when in fact most of it 
> is backed by your cheap and slow disk storage. Virtual memory 
> it is.

It also exists to solve the relocation problem. :)

> Position-independent code is a good thing, but it's not always 
> cheap (the CPU simply may have no decent PC-relative addressing) 
> and it itself may need a tiny bit of relocation.

> Let's say you have this tiny bit of C code: 

> #include <stdio.h> 

> int a = 123; 
> int* pa = &a; 

> int main(void) 
> { 
>   printf("%d\n", *pa); 
>   return 0; 
> } 

> On the x86, direct calls are PC-relative, so calling printf() 
> may be deemed covered in terms of position independence. 
> But data accesses to pa and a in non-64-bit modes are not 
> PC-relative. Hence relocations and/or complex indirection 
> schemes. 

> OTOH, in the 64-bit mode you can access both pa and a relative 
> to PC. However, how does pa get its initial value, the address 
> of a? There must be some code somewhere that takes the address 
> of a and stores it in memory at the address of pa. That is a form 
> of relocation. Bummer! 

But what does ELF have to do with this whole thing? I understand that certain
things are relative and certain things have to be relocated. But what does ELF
have to do with it? Why can't we just compile position independent code when we
need it and when not, use pure binary files? Obviously we would need paging in
order to solve the relocation problem with these pure binary files, but wouldn't
the same thing be necessary for ELFs?

Mike Gonta wrote:

> No need to if you're going to generate a flat binary file. 
> Simple link the object files and specify: 

> OUTPUT_FORMAT("binary") 

> in the linker file.

>> because otherwise, I won’t know how to jump into the 
>> executable from an assembly file in my OS. 

> Simply link with the asm object file and include a jmp or 
> call to the function name used in the "C" file. 
> Another simple technique to use when running a loaded flat 
> binary from the OS is to call the beginning address of the 
> loaded file. In this case since you can never be sure of 
> where the actually address of the "main" function will be in 
> the actual binary simply put an inline asm statement at the 
> end of a "#include"d file: 

>   __asm__ ("jmp main"); 

> and the linker will take care of the rest. 
> Also, for example, if you load the the file to (for example) 
> 0x400000, you can call it from "C" in the OS loader with: 

>   ((int (*)(void ))0x400000)(); 

> (with the appropriate return type and parameters). 

So let's say I write an assembly file and a C file and then I link them together.
How would I call this executable file from an assembly file in my OS? If I load
it to 0x400000, can I just write "jmp 0x400000"? I think this would only work if
the code of the assembly file (that was linked in) is placed (by the linker)
right at the beginning of the resulting executable. Would that be the case?

Thank you very much,
Isaac D. Cohen

[toc] | [prev] | [next] | [standalone]


#9565

From"Mike Gonta" <mikegonta@gmail.com>
Date2016-05-25 19:03 -0400
Message-ID<ni5b17$10pn$1@gioia.aioe.org>
In reply to#9564
"Isaac D. Cohen" wrote:

> So let's say I write an assembly file and a C file and
> then I link them together. How would I call this
> executable file from an assembly file in my OS? If I load
> it to 0x400000, can I just write "jmp 0x400000"? I think
> this would only work if the code of the assembly file
> (that was linked in) is placed (by the linker) right at
> the beginning of the resulting executable. Would that be
> the case?

If the loaded binary is an asm file then it is up to you to
make sure that the first instruction is the start or will
get to the start (such as "jmp start") and link the asm file
first. "start" of course could be a function in the "C" file.
If the loaded binary is a "C" file then use the #include
__asm__ ("jmp main");


Mike Gonta
look and see - many look but few see

http://mikegonta.com
http://tawk.to/mikegonta

[toc] | [prev] | [next] | [standalone]


#9569

From"Isaac D. Cohen" <8switchsoftware@gmail.com>
Date2016-05-26 14:51 -0700
Message-ID<d26c82e5-f9db-4247-80a7-97f5157d84e3@googlegroups.com>
In reply to#9565
Mike Gonta wrote:

> "Isaac D. Cohen" wrote:

>> So let's say I write an assembly file and a C file and
>> then I link them together. How would I call this
>> executable file from an assembly file in my OS? If I load
>> it to 0x400000, can I just write "jmp 0x400000"? I think
>> this would only work if the code of the assembly file
>> (that was linked in) is placed (by the linker) right at
>> the beginning of the resulting executable. Would that be
>> the case?

> If the loaded binary is an asm file then it is up to you to
> make sure that the first instruction is the start or will
> get to the start (such as "jmp start") and link the asm file
> first. "start" of course could be a function in the "C" file.
> If the loaded binary is a "C" file then use the #include
> __asm__ ("jmp main");

So how would we implement this? Let's say we have a C file that looks something like this:

int a=10;
int b=20;
int main(){
int c=a+b;}

Note that this example file does not include any system libraries (or any libraries at all, for that matter) such as "stdio.h".

So we can compile this independent code as follows:

gcc -c <filename.c>

But wait. That just created an ELF object file. Furthermore, we can only link with an assembly file that has also been assembled into an object file. We can't link with pure binary. So how can we create a pure binary kernel?

Thank you very much,
Isaac D. Cohen

[toc] | [prev] | [next] | [standalone]


#9573

FromRod Pemberton <NoHaveNotOne@bcczxcfre.cmm>
Date2016-05-27 02:55 -0400
Message-ID<20160527025559.72612eda@_>
In reply to#9569
On Thu, 26 May 2016 14:51:42 -0700 (PDT)
"Isaac D. Cohen" <8switchsoftware@gmail.com> wrote:

> So how can we create a pure binary kernel?

A more important question might be, "Why do you want one?" ...

You generally need a pure binary for a bootable code such as a
bootloader, but usually not much else.  A bootloader will usually only
start an OS image that is _NOT_ a pure binary.  Bootloaders will start
execution of an OS image which has a specific executable or object
format or a special header, such as ELF, or DOS OMF, or COFF, or
whatever M$ uses, or that which has a Multiboot header, etc.

If you've coded your own bootloader, then you just need to call or jump
to the entry point in your executable image, e.g., to main() for C or a
"start" label for assembly.  Usually, C compilers include some assembly
labels which are accessible, such as some variation of "start".
However, if the compiler or assembler produces an executable format,
such as ELF, COFF, PE, etc, then the executable header provides an
entry point to start execution.  I.e., this has been done for you, if
your bootloader can obtain information from the executable header.

You definitely need to make sure the kernel is not dependent on
any system libraries, e.g., static code, or not doesn't use them.  This
usually requires some compiler specific flags to warn or error if you
do.

Of course, you can, if careful, use some system code since some of it
won't be dependent on the host OS.  These will be very basic functions.


Rod Pemberton

[toc] | [prev] | [next] | [standalone]


#9578

From"Isaac D. Cohen" <8switchsoftware@gmail.com>
Date2016-05-27 13:43 -0700
Message-ID<b0063221-fd4c-4276-9ffa-da12d0bfe821@googlegroups.com>
In reply to#9573
Rod Pemberton wrote:


>> So how can we create a pure binary kernel?
 
> A more important question might be, "Why do you want one?" ...
 
> You generally need a pure binary for a bootable code such as a
> bootloader, but usually not much else.  A bootloader will usually only
> start an OS image that is _NOT_ a pure binary.  Bootloaders will start
> execution of an OS image which has a specific executable or object
> format or a special header, such as ELF, or DOS OMF, or COFF, or
> whatever M$ uses, or that which has a Multiboot header, etc.

Well, originally, that's what I wanted to do. But when I has many questions about
ELF Mike suggested that I use plain binary so that I can simply jump to the
address at which I loaded the file rather than having to read all those headers
first.

Thank you very much,
Isaac D. Cohen

[toc] | [prev] | [next] | [standalone]


#9579

From"Mike Gonta" <mikegonta@gmail.com>
Date2016-05-27 17:40 -0400
Message-ID<niaesn$1t8c$1@gioia.aioe.org>
In reply to#9578
"Isaac D. Cohen" wrote:
> Rod Pemberton wrote:
>> "Isaac D. Cohen" wrote:
>>> So how can we create a pure binary kernel?
>> A more important question might be, "Why do you want
>> one?" ...

> Well, originally, that's what I wanted to do.

No it's not.
"Isaac D. Cohen" wrote:
>>>> In any case, I'm trying to figure out how to include C/C++
>>>> in my operating system. So I googled around and found that
>>>> I have to cross-compile the C/C++ file into some kind of
>>>> format, for example ELF. So my first question is, why? Why
>>>> can't the compiler just generate plain binary files?

The compiler generates object files and the linker produces
the binary.

> But when I has many questions about ELF Mike suggested
> that I use plain binary....

It's simple to link the ELF object file to produce a plain
binary (and no knowledge of ELF is required).

> ....so that I can simply jump to the address at which I
> loaded the file rather than having to read all those
> headers first.

I thought that others (as well as yourself) might be
interested in how to do things by "not following the rules".


Mike Gonta
look and see - many look but few see

http://mikegonta.com
http://tawk.to/mikegonta

[toc] | [prev] | [next] | [standalone]


#9580

From"Isaac D. Cohen" <8switchsoftware@gmail.com>
Date2016-05-28 20:15 -0700
Message-ID<a577f76c-aaad-4a79-930b-ccee99b3f9e2@googlegroups.com>
In reply to#9579
Mike Gonta wrote:
> "Isaac D. Cohen" wrote:
>> Rod Pemberton wrote:
>>> "Isaac D. Cohen" wrote:
>>>> So how can we create a pure binary kernel?
>>> A more important question might be, "Why do you want
>>> one?" ...
 
>> Well, originally, that's what I wanted to do.
 
> No it's not.

No use arguing over facts.

> "Isaac D. Cohen" wrote:
>>>>> In any case, I'm trying to figure out how to include C/C++
>>>>> in my operating system. So I googled around and found that
>>>>> I have to cross-compile the C/C++ file into some kind of
>>>>> format, for example ELF. So my first question is, why? Why
>>>>> can't the compiler just generate plain binary files?

> The compiler generates object files and the linker produces
> the binary.
 
>> But when I has many questions about ELF Mike suggested
>> that I use plain binary....

> It's simple to link the ELF object file to produce a plain
> binary (and no knowledge of ELF is required).
 
>> ....so that I can simply jump to the address at which I
>> loaded the file rather than having to read all those
>> headers first.

> I thought that others (as well as yourself) might be
> interested in how to do things by "not following the rules".

I tried building a kernel as you say (i.e. compiling into ELFs and then linking
into binary) and jumping to the address at which I loaded the kernel, but it
caused a page fault. I would guess that the reason for this is because the file
has some kind of format or another (not ELF) and just jumping to the beginning of
it is making the CPU execute something that is not code (or the wrong code).

Thank you very much,
Isaac D. Cohen

"Religion is an illusion and it derives its strength from the fact that it falls
in with our instinctual desires." - Sigmund Freud

[toc] | [prev] | [next] | [standalone]


#9583

FromRod Pemberton <NoHaveNotOne@bcczxcfre.cmm>
Date2016-05-29 02:35 -0400
Message-ID<20160529023551.23d916a9@_>
In reply to#9580
On Sat, 28 May 2016 20:15:17 -0700 (PDT)
"Isaac D. Cohen" <8switchsoftware@gmail.com> wrote:

> I tried building a kernel as you say (i.e. compiling into ELFs and
> then linking into binary) and jumping to the address at which I
> loaded the kernel, but it caused a page fault. I would guess that the
> reason for this is because the file has some kind of format or
> another (not ELF) and just jumping to the beginning of it is making
> the CPU execute something that is not code (or the wrong code).

A page fault?  Why would you have paging enabled?  Isn't it a bit early
in development to have activated paging?  If you haven't implemented
paging yet, as I would suspect.  Then, it's a problem with your
emulator.  Otherwise, disable paging until after everything works.


Rod Pemberton

[toc] | [prev] | [next] | [standalone]


#9661

From"Isaac D. Cohen" <8switchsoftware@gmail.com>
Date2016-06-15 13:51 -0700
Message-ID<f6fff84f-3f54-44c7-898b-c84183c36a20@googlegroups.com>
In reply to#9583
I wrote:

> I tried building a kernel as you say (i.e. compiling into ELFs and 
> then linking into binary) and jumping to the address at which I 
> loaded the kernel, but it caused a page fault. I would guess that the 
> reason for this is because the file has some kind of format or 
> another (not ELF) and just jumping to the beginning of it is making 
> the CPU execute something that is not code (or the wrong code). 

Well, as it turns out, I guessed wrong. The page fault was because of an error in my linker script. I fixed it now and all is well.

Thank you everyone (especially Mike Gonta and Rod Pemberton) for your help!

Isaac D. Cohen

[toc] | [prev] | [next] | [standalone]


#9574

FromRod Pemberton <NoHaveNotOne@bcczxcfre.cmm>
Date2016-05-27 03:09 -0400
Message-ID<20160527030956.5383a466@_>
In reply to#9569
On Thu, 26 May 2016 14:51:42 -0700 (PDT)
"Isaac D. Cohen" <8switchsoftware@gmail.com> wrote:

> So we can compile this independent code as follows:
> 
> gcc -c <filename.c>
> 
> But wait. That just created an ELF object file. Furthermore, we can
> only link with an assembly file that has also been assembled into an
> object file. We can't link with pure binary. So how can we create a
> pure binary kernel?

After compiling or assembling your code to object file, but prior to
linking, you may be able to use a linker line like below with the object
file.  This is for GNU ld:

ld --oformat binary -Ttext=0xORG -e start -o file.bin file.o

You should be able to put multiple objects on the ld line to be
linked.  I'm not sure if this will link together what you need.

(If you're not using GNU toolchain, that will be something different.
You'll need to specify which compiler or assembler or toolchain.)

"start" is the entry label.  0xORG is the hexadecimal start address or
offset the code is being compiled for.

That would require a "start" label in GAS assembly like this:

.global _start
_start:

For 64-bit Linux, GCC inserts a "cmain" label:

.globl cmain
cmain:


I'm sure there are some missing details there that you'll have to work
out by reading the manuals or or trial and error or help options or
searching the net.


Rod Pemberton

[toc] | [prev] | [next] | [standalone]


#9575

From"Alexei A. Frounze" <alexfrunews@gmail.com>
Date2016-05-27 00:10 -0700
Message-ID<dd82b9b8-a943-4e41-b73f-620971caf1bd@googlegroups.com>
In reply to#9569
On Thursday, May 26, 2016 at 2:51:43 PM UTC-7, Isaac D. Cohen wrote:
...
> gcc -c <filename.c>
> 
> But wait. That just created an ELF object file. Furthermore, we can only link with an assembly file that has also been assembled into an object file. We can't link with pure binary. So how can we create a pure binary kernel?
> 

You can tinker with the linker (some support generation of
raw/flat/whatever executables; AFAIK you may need a special
version of GNU ld, not just any, to be able to make such
binaries) or convert the executable into what you want.

I have my own linker that can produce raw/flat executables,
but it doesn't support 64-bit ELF objects, so it's probably
of no use to you (oh, and I didn't test it with gcc's output,
only with ELF files produced by NASM, YASM and FASM since
my C compiler generates assembly code that needs assembling).

Alex

[toc] | [prev] | [next] | [standalone]


#9605

FromRod Pemberton <NoHaveNotOne@bcczxcfre.cmm>
Date2016-06-02 16:25 -0400
Message-ID<20160602162528.39880eb6@_>
In reply to#9569
On Thu, 26 May 2016 14:51:42 -0700 (PDT)
"Isaac D. Cohen" <8switchsoftware@gmail.com> wrote:


> So how would we implement this?

So, I ran across another project that uses the following options to link
NASM code with GCC C code using a linker script and produces a binary.
It generates a binary from the linked executable.

nasm -f aout
gcc -fno-builtin
ld -nostdlib -T linker.ld
objcopy -O binary


Rod Pemberton

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | alt.os.development


csiph-web