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