| 1 | /* $Id: elf2lx.cpp,v 1.5 2000-12-11 06:53:48 bird Exp $ | 
|---|
| 2 | * | 
|---|
| 3 | * Elf2Lx - implementation. | 
|---|
| 4 | * | 
|---|
| 5 | * Copyright (c) 1999-2000 knut st. osmundsen (knut.stange.osmundsen@mynd.no) | 
|---|
| 6 | * | 
|---|
| 7 | * Project Odin Software License can be found in LICENSE.TXT | 
|---|
| 8 | * | 
|---|
| 9 | */ | 
|---|
| 10 |  | 
|---|
| 11 |  | 
|---|
| 12 | /******************************************************************************* | 
|---|
| 13 | *   Defined Constants And Macros                                               * | 
|---|
| 14 | *******************************************************************************/ | 
|---|
| 15 | #define FOR_EXEHDR 1                    /* To make all object flags OBJ???. */ | 
|---|
| 16 | #define INCL_DOSERRORS                  /* DOS Error codes. */ | 
|---|
| 17 | #ifdef RING0 | 
|---|
| 18 | #define INCL_NOAPI                  /* RING0: No apis. */ | 
|---|
| 19 | #else /*RING3*/ | 
|---|
| 20 | #define INCL_DOSPROCESS             /* RING3: DosSleep. */ | 
|---|
| 21 | #endif | 
|---|
| 22 |  | 
|---|
| 23 | /******************************************************************************* | 
|---|
| 24 | *   Header Files                                                               * | 
|---|
| 25 | *******************************************************************************/ | 
|---|
| 26 | #include <os2.h>                        /* OS/2 header file. */ | 
|---|
| 27 | #include "types.h"                      /* Types used by the next two files. */ | 
|---|
| 28 | #include <newexe.h>                     /* OS/2 NE structs and definitions. */ | 
|---|
| 29 | #include <exe386.h>                     /* OS/2 LX structs and definitions. */ | 
|---|
| 30 |  | 
|---|
| 31 | #include "devSegDf.h"                   /* Win32k segment definitions. */ | 
|---|
| 32 |  | 
|---|
| 33 | #include "malloc.h"                     /* win32k malloc (resident). Not C library! */ | 
|---|
| 34 | #include "smalloc.h"                    /* win32k swappable heap. */ | 
|---|
| 35 | #include "rmalloc.h"                    /* win32k resident heap. */ | 
|---|
| 36 |  | 
|---|
| 37 | #include <string.h>                     /* C library string.h. */ | 
|---|
| 38 | #include <stdlib.h>                     /* C library stdlib.h. */ | 
|---|
| 39 | #include <stddef.h>                     /* C library stddef.h. */ | 
|---|
| 40 | #include <stdarg.h>                     /* C library stdarg.h. */ | 
|---|
| 41 |  | 
|---|
| 42 | #include "vprintf.h"                    /* win32k printf and vprintf. Not C library! */ | 
|---|
| 43 | #include "dev32.h"                      /* 32-Bit part of the device driver. (SSToDS) */ | 
|---|
| 44 | #include "OS2Krnl.h"                    /* kernel structs.  (SFN) */ | 
|---|
| 45 | #ifdef RING0 | 
|---|
| 46 | #include "ldrCalls.h"               /* ldr* calls. (ldrRead) */ | 
|---|
| 47 | #endif | 
|---|
| 48 |  | 
|---|
| 49 | #include "elf.h"                        /* Elf binary format definitions. */ | 
|---|
| 50 | #include "modulebase.h"                 /* ModuleBase class definitions, ++. */ | 
|---|
| 51 | #include "elf2lx.h"                     /* Elf2Lx class definitions.  */ | 
|---|
| 52 |  | 
|---|
| 53 |  | 
|---|
| 54 |  | 
|---|
| 55 | /** | 
|---|
| 56 | * Initiation and termination code for libraries. | 
|---|
| 57 | * | 
|---|
| 58 | * How will OS2NIX initiate libraries? | 
|---|
| 59 | * -A library will register with the OS2NIX dll on init and deregister on | 
|---|
| 60 | *  termintation. | 
|---|
| 61 | * -If this is before the executable has registered its self, the library | 
|---|
| 62 | *  will not be initiated yet. The initiation will take place when the | 
|---|
| 63 | *  executable register. | 
|---|
| 64 | * -If it is a dynamically loaded library, we'll initiate it during registation. | 
|---|
| 65 | *  Or we could initiate it when the load library call returns, ie. after | 
|---|
| 66 | *  DosLoadModule. It depends on how we may resolv addresses of external symbols. | 
|---|
| 67 | * | 
|---|
| 68 | */ | 
|---|
| 69 | static UCHAR achInitTermCode[] = | 
|---|
| 70 | { | 
|---|
| 71 | 0xCC | 
|---|
| 72 | }; | 
|---|
| 73 |  | 
|---|
| 74 |  | 
|---|
| 75 | /** | 
|---|
| 76 | * Startup code for executables. | 
|---|
| 77 | * | 
|---|
| 78 | * How will OS2NIX start an Elf executable? | 
|---|
| 79 | * -An executable will register with the OS2NIX dll on startup. | 
|---|
| 80 | * -During this registration it'll resolv addresses of external symbols for | 
|---|
| 81 | *  the executable and all the libraries registered at this time. It will then | 
|---|
| 82 | *  call the initiation routines for the libraries. Finally it will start | 
|---|
| 83 | *  the executable. | 
|---|
| 84 | * -If this was a forked process then other steps has to be taken during registration? | 
|---|
| 85 | * | 
|---|
| 86 | */ | 
|---|
| 87 | static UCHAR achStartupCode[] = | 
|---|
| 88 | { | 
|---|
| 89 | 0xCC | 
|---|
| 90 | }; | 
|---|
| 91 |  | 
|---|
| 92 |  | 
|---|
| 93 |  | 
|---|
| 94 | /** | 
|---|
| 95 | * Constructor. Initiates all data members and sets hFile. | 
|---|
| 96 | * @param     hFile  Filehandle. | 
|---|
| 97 | * @status    Partially implemented. | 
|---|
| 98 | * @author    knut st. osmundsen | 
|---|
| 99 | * @remark    Remember to update this everytime a new parameter is added. | 
|---|
| 100 | */ | 
|---|
| 101 | Elf2Lx::Elf2Lx(SFN hFile) : | 
|---|
| 102 | ModuleBase(hFile) | 
|---|
| 103 | { | 
|---|
| 104 | memset(&LXHdr, 0, sizeof(LXHdr)); | 
|---|
| 105 | LXHdr.e32_magic[0]  = E32MAGIC1; | 
|---|
| 106 | LXHdr.e32_magic[1]  = E32MAGIC2; | 
|---|
| 107 | LXHdr.e32_border    = E32LEBO; | 
|---|
| 108 | LXHdr.e32_worder    = E32LEWO; | 
|---|
| 109 | LXHdr.e32_level     = E32LEVEL; | 
|---|
| 110 | LXHdr.e32_cpu       = E32CPU386; | 
|---|
| 111 | LXHdr.e32_os        = NE_OS2; | 
|---|
| 112 | LXHdr.e32_pagesize  = PAGESIZE; | 
|---|
| 113 | LXHdr.e32_objtab    = sizeof(LXHdr); | 
|---|
| 114 | } | 
|---|
| 115 |  | 
|---|
| 116 |  | 
|---|
| 117 | /** | 
|---|
| 118 | * Destructor. | 
|---|
| 119 | * @status    stub | 
|---|
| 120 | * @author    knut st. osmundsen | 
|---|
| 121 | */ | 
|---|
| 122 | Elf2Lx::~Elf2Lx() | 
|---|
| 123 | { | 
|---|
| 124 |  | 
|---|
| 125 | } | 
|---|
| 126 |  | 
|---|
| 127 |  | 
|---|
| 128 | /** | 
|---|
| 129 | * Initiates the Elf2Lx object - builds the virtual LX image. | 
|---|
| 130 | * When this function completes the object is no longer in init-mode. | 
|---|
| 131 | * @returns   NO_ERROR on success. | 
|---|
| 132 | *            ERROR_NOT_ENOUGH_MEMORY | 
|---|
| 133 | *            ERROR_INVALID_EXE_SIGNATURE | 
|---|
| 134 | *            ERROR_BAD_EXE_FORMAT | 
|---|
| 135 | *            Error code returned by ReadAt. | 
|---|
| 136 | *            Error codes from the make* methods. | 
|---|
| 137 | * @param     pszFilename  Module filename. | 
|---|
| 138 | * @precond   Called in init-mode. | 
|---|
| 139 | * @sketch | 
|---|
| 140 | *            0. pszFilename & pszModuleName. | 
|---|
| 141 | *            1. Read the Elf header. | 
|---|
| 142 | *            2. Verify the header. | 
|---|
| 143 | *            3. Read Program headers. | 
|---|
| 144 | *            4. | 
|---|
| 145 | * | 
|---|
| 146 | *            5. | 
|---|
| 147 | *            6. | 
|---|
| 148 | *            7. Start converting the sections by adding the headerobject. (headerobject, see previous chapter). | 
|---|
| 149 | *            8. Iterate thru the sectiontable converting the section to objects. | 
|---|
| 150 | *              8a. Convert characteristics to flags | 
|---|
| 151 | *              8b. Virtual/physical size (see note in code) | 
|---|
| 152 | *              8c. Add object. | 
|---|
| 153 | *            9.Find where the TIB fix is to be placed. (see 3.1.1 for placements.) Place the TIB fix. | 
|---|
| 154 | *              9a. At the end of the header object. | 
|---|
| 155 | *              9b. After MZ-Header (In the dos stub!). | 
|---|
| 156 | *              9c.Add separate TIBFix object. | 
|---|
| 157 | *            10.Add stack object. | 
|---|
| 158 | *            11.Align section. (Fix which is applied to EXEs/Dlls which contain no fixups and has an | 
|---|
| 159 | *               alignment which is not a multiple of 64Kb. The sections are concatenated into one big object. | 
|---|
| 160 | *            12.Update the LXHeader with info which is finalized now. (Stacksize, GUI/CUI, characteristics,...) | 
|---|
| 161 | *            13.Convert exports. | 
|---|
| 162 | *            14.Convert base relocations (fixups). Remember to add the fixup for RegisterPe2LxDll/Exe. | 
|---|
| 163 | *            15.Make object table. | 
|---|
| 164 | *            16.Make object page table. | 
|---|
| 165 | *            17.Completing the LX header. | 
|---|
| 166 | *            18.Set offLXFile in the object array. | 
|---|
| 167 | *            19.The conversion method is completed. Object is now usable. | 
|---|
| 168 | *            20.Dump virtual LX-file | 
|---|
| 169 | *            return successfully. | 
|---|
| 170 | * @status    Completely implemented; tested. | 
|---|
| 171 | * @author    knut st. osmundsen | 
|---|
| 172 | */ | 
|---|
| 173 | ULONG Elf2Lx::init(PCSZ pszFilename) | 
|---|
| 174 | { | 
|---|
| 175 | APIRET      rc; | 
|---|
| 176 | unsigned    cb;                     /* helper variable, used to hold sizes in bytes. */ | 
|---|
| 177 |  | 
|---|
| 178 | #ifdef DEBUG | 
|---|
| 179 | if (!fInitTime) | 
|---|
| 180 | { | 
|---|
| 181 | printIPE(("init(..) called when not in init mode!\n")); | 
|---|
| 182 | return ERROR_INITMETHOD_NOT_INITTIME; | 
|---|
| 183 | } | 
|---|
| 184 | #endif | 
|---|
| 185 |  | 
|---|
| 186 | printInf(("Started processing %s\n", pszFilename)); | 
|---|
| 187 |  | 
|---|
| 188 | /* | 
|---|
| 189 | * 0.pszFilename & pszModuleName. | 
|---|
| 190 | */ | 
|---|
| 191 | rc = ModuleBase::init(pszFilename); | 
|---|
| 192 | if (rc != NO_ERROR) | 
|---|
| 193 | return rc; | 
|---|
| 194 |  | 
|---|
| 195 | /* | 
|---|
| 196 | * 1.Read the Elf header. | 
|---|
| 197 | */ | 
|---|
| 198 | pEhdr = (Elf32_Ehdr*)malloc(sizeof(*pEhdr)); | 
|---|
| 199 | if (pEhdr == NULL) | 
|---|
| 200 | return ERROR_NOT_ENOUGH_MEMORY; | 
|---|
| 201 | rc = ReadAt(hFile, pEhdr->e_phoff, paPhdrs, pEhdr->e_phentsize * pEhdr->e_phnum); | 
|---|
| 202 | if (rc != NO_ERROR) | 
|---|
| 203 | { | 
|---|
| 204 | printErr(("Failed to read Elf header\n")); | 
|---|
| 205 | return rc; | 
|---|
| 206 | } | 
|---|
| 207 |  | 
|---|
| 208 | /* | 
|---|
| 209 | * 2.Check that it is a valid header. Fail if invalid. | 
|---|
| 210 | */ | 
|---|
| 211 | if (!Elf2Lx::validHeader(pEhdr)) | 
|---|
| 212 | { | 
|---|
| 213 | printErr(("Not a valid Elf format\n")); | 
|---|
| 214 | return ERROR_BAD_EXE_FORMAT; | 
|---|
| 215 | } | 
|---|
| 216 |  | 
|---|
| 217 | /* | 
|---|
| 218 | * 3.Read program table. | 
|---|
| 219 | */ | 
|---|
| 220 | cb = pEhdr->e_phentsize * pEhdr->e_phnum; | 
|---|
| 221 | paPhdrs = (Elf32_Phdr*)malloc(cb); | 
|---|
| 222 | if (paPhdrs == NULL) | 
|---|
| 223 | return ERROR_NOT_ENOUGH_MEMORY; | 
|---|
| 224 | rc = ReadAt(hFile, pEhdr->e_phoff, paPhdrs, cb); | 
|---|
| 225 | if (rc != NO_ERROR) | 
|---|
| 226 | { | 
|---|
| 227 | printErr(("Failed to read program headers, off=0x%08x, size=0x%08x\n", | 
|---|
| 228 | pEhdr->e_phoff, cb)); | 
|---|
| 229 | return rc; | 
|---|
| 230 | } | 
|---|
| 231 |  | 
|---|
| 232 | /* | 
|---|
| 233 | * 4. | 
|---|
| 234 | */ | 
|---|
| 235 |  | 
|---|
| 236 | return rc; | 
|---|
| 237 | } | 
|---|
| 238 |  | 
|---|
| 239 |  | 
|---|
| 240 |  | 
|---|
| 241 |  | 
|---|
| 242 | /** | 
|---|
| 243 | * Check if the passed in header struct is an Elf header valid for | 
|---|
| 244 | * this system. | 
|---|
| 245 | * @returns   TRUE:  valid header. | 
|---|
| 246 | *            FALSE: invalid header. | 
|---|
| 247 | * @param     pEhdr  Pointer to elf header. | 
|---|
| 248 | * @status    completely implemented. | 
|---|
| 249 | * @author    knut st. osmundsen (knut.stange.osmundsen@mynd.no) | 
|---|
| 250 | */ | 
|---|
| 251 | BOOL Elf2Lx::validHeader(Elf32_Ehdr *pEhdr) | 
|---|
| 252 | { | 
|---|
| 253 | /* | 
|---|
| 254 | * Checks. | 
|---|
| 255 | */ | 
|---|
| 256 | if (*(PULONG)pEhdr == ELFMAGICLSB                   /* Elf magic */ | 
|---|
| 257 | && pEhdr->e_ident[EI_CLASS] == ELFCLASS32       /* 32-bit format */ | 
|---|
| 258 | && pEhdr->e_ident[EI_DATA] == ELFDATA2LSB       /* Little endian */ | 
|---|
| 259 | && pEhdr->e_ident[EI_VERSION] == EV_CURRENT     /* Format version */ | 
|---|
| 260 | && (pEhdr->e_type == ET_EXEC ||                 /* Filetype Exec or Library */ | 
|---|
| 261 | pEhdr->e_type == ET_DYN) | 
|---|
| 262 | && (pEhdr->e_machine == EM_386 ||               /* Machine type 386 (or 486) */ | 
|---|
| 263 | pEhdr->e_machine == EM_486) | 
|---|
| 264 | && pEhdr->e_version == EV_CURRENT               /* Format version */ | 
|---|
| 265 | && pEhdr->e_flags == EF_386_NONE                /* No flags for 386 and 486 */ | 
|---|
| 266 | && pEhdr->e_ehsize >= sizeof(*pEhdr)            /* Elf header not smaller than ours. */ | 
|---|
| 267 | && pEhdr->e_phentsize >= sizeof(Elf32_Phdr)     /* Program header size not smaller than ours. */ | 
|---|
| 268 | && pEhdr->e_shentsize >= sizeof(Elf32_Shdr)     /* Section header size not smaller than ours. */ | 
|---|
| 269 | && pEhdr->e_phnum < 128                         /* An image with more that 128 program headers is supicious! */ | 
|---|
| 270 | ) | 
|---|
| 271 | return TRUE; | 
|---|
| 272 | return FALSE; | 
|---|
| 273 | } | 
|---|
| 274 |  | 
|---|