Ejemplo n.º 1
0
Archivo: ld.c Proyecto: MarginC/kame
int
ldsize(dev_t dev)
{
	struct ld_softc *sc;
	int part, unit, omask, size;

	unit = DISKUNIT(dev);
	if ((sc = device_lookup(&ld_cd, unit)) == NULL)
		return (ENODEV);
	if ((sc->sc_flags & LDF_ENABLED) == 0)
		return (ENODEV);
	part = DISKPART(dev);

	omask = sc->sc_dk.dk_openmask & (1 << part);

	if (omask == 0 && ldopen(dev, 0, S_IFBLK, NULL) != 0)
		return (-1);
	else if (sc->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
		size = -1;
	else
		size = sc->sc_dk.dk_label->d_partitions[part].p_size *
		    (sc->sc_dk.dk_label->d_secsize / DEV_BSIZE);
	if (omask == 0 && ldclose(dev, 0, S_IFBLK, NULL) != 0)
		return (-1);

	return (size);
}
Ejemplo n.º 2
0
/*
 * Build the export table from the XCOFF .loader section.
 */
static int readExports(ModulePtr mp)
{
	LDFILE *ldp = NULL;
	SCNHDR sh, shdata;
	LDHDR *lhp;
	char *ldbuf;
	LDSYM *ls;
	int i;
	ExportPtr ep;

	if ((ldp = ldopen(mp->name, ldp)) == NULL) {
		struct ld_info *lp;
		char *buf;
		int size = 4*1024;
		if (errno != ENOENT) {
			errvalid++;
			strcpy(errbuf, "readExports: ");
			strcat(errbuf, strerror(errno));
			return -1;
		}
		/*
		 * The module might be loaded due to the LIBPATH
		 * environment variable. Search for the loaded
		 * module using L_GETINFO.
		 */
		if ((buf = malloc(size)) == NULL) {
			errvalid++;
			strcpy(errbuf, "readExports: ");
			strcat(errbuf, strerror(errno));
			return -1;
		}
		while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
			free(buf);
			size += 4*1024;
			if ((buf = malloc(size)) == NULL) {
				errvalid++;
				strcpy(errbuf, "readExports: ");
				strcat(errbuf, strerror(errno));
				return -1;
			}
		}
		if (i == -1) {
			errvalid++;
			strcpy(errbuf, "readExports: ");
			strcat(errbuf, strerror(errno));
			free(buf);
			return -1;
		}
		/*
		 * Traverse the list of loaded modules. The entry point
		 * returned by load() does actually point to the data
		 * segment origin.
		 */
		lp = (struct ld_info *)buf;
		while (lp) {
			if (lp->ldinfo_dataorg == mp->entry) {
				ldp = ldopen(lp->ldinfo_filename, ldp);
				break;
			}
			if (lp->ldinfo_next == 0)
				lp = NULL;
			else
				lp = (struct ld_info *)((char *)lp + lp->ldinfo_next);
		}
		free(buf);
		if (!ldp) {
			errvalid++;
			strcpy(errbuf, "readExports: ");
			strcat(errbuf, strerror(errno));
			return -1;
		}
	}
	if (TYPE(ldp) != U802TOCMAGIC) {
		errvalid++;
		strcpy(errbuf, "readExports: bad magic");
		while(ldclose(ldp) == FAILURE)
			;
		return -1;
	}
	/*
	 * Get the padding for the data section. This is needed for
	 * AIX 4.1 compilers. This is used when building the final
	 * function pointer to the exported symbol.
	 */
	if (ldnshread(ldp, _DATA, &shdata) != SUCCESS) {
		errvalid++;
		strcpy(errbuf, "readExports: cannot read data section header");
		while(ldclose(ldp) == FAILURE)
			;
		return -1;
	}
	if (ldnshread(ldp, _LOADER, &sh) != SUCCESS) {
		errvalid++;
		strcpy(errbuf, "readExports: cannot read loader section header");
		while(ldclose(ldp) == FAILURE)
			;
		return -1;
	}
	/*
	 * We read the complete loader section in one chunk, this makes
	 * finding long symbol names residing in the string table easier.
	 */
	if ((ldbuf = (char *)malloc(sh.s_size)) == NULL) {
		errvalid++;
		strcpy(errbuf, "readExports: ");
		strcat(errbuf, strerror(errno));
		while(ldclose(ldp) == FAILURE)
			;
		return -1;
	}
	if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK) {
		errvalid++;
		strcpy(errbuf, "readExports: cannot seek to loader section");
		free(ldbuf);
		while(ldclose(ldp) == FAILURE)
			;
		return -1;
	}
	if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1) {
		errvalid++;
		strcpy(errbuf, "readExports: cannot read loader section");
		free(ldbuf);
		while(ldclose(ldp) == FAILURE)
			;
		return -1;
	}
	lhp = (LDHDR *)ldbuf;
	ls = (LDSYM *)(ldbuf+LDHDRSZ);
	/*
	 * Count the number of exports to include in our export table.
	 */
	for (i = lhp->l_nsyms; i; i--, ls++) {
		if (!LDR_EXPORT(*ls))
			continue;
		mp->nExports++;
	}
	if ((mp->exports = (ExportPtr)calloc(mp->nExports, sizeof(*mp->exports))) == NULL) {
		errvalid++;
		strcpy(errbuf, "readExports: ");
		strcat(errbuf, strerror(errno));
		free(ldbuf);
		while(ldclose(ldp) == FAILURE)
			;
		return -1;
	}
	/*
	 * Fill in the export table. All entries are relative to
	 * the entry point we got from load.
	 */
	ep = mp->exports;
	ls = (LDSYM *)(ldbuf+LDHDRSZ);
	for (i = lhp->l_nsyms; i; i--, ls++) {
		char *symname;
		char tmpsym[SYMNMLEN+1];
		if (!LDR_EXPORT(*ls))
			continue;
		if (ls->l_zeroes == 0)
			symname = ls->l_offset+lhp->l_stoff+ldbuf;
		else {
			/*
			 * The l_name member is not zero terminated, we
			 * must copy the first SYMNMLEN chars and make
			 * sure we have a zero byte at the end.
			 */
			strncpy(tmpsym, ls->l_name, SYMNMLEN);
			tmpsym[SYMNMLEN] = '\0';
			symname = tmpsym;
		}
		ep->name = malloc((unsigned) (strlen(symname) + 1));
		strcpy(ep->name, symname);
		ep->addr = (void *)((unsigned long)mp->entry +
					ls->l_value - shdata.s_vaddr);
		ep++;
	}
	free(ldbuf);
	while(ldclose(ldp) == FAILURE)
		;
	return 0;
}
Ejemplo n.º 3
0
void Object::load_object(bool sharedLibrary) {
    char* file = strdup(file_.c_str());
    bool        did_open = false, success=true, text_read=false;
    LDFILE      *ldptr = NULL;
    HDRR        sym_hdr;
    pCHDRR      sym_tab_ptr = NULL;
    long        index=0;
    SYMR        symbol;
    unsigned short sectindex=1;
    SCNHDR      secthead;
    filehdr     fhdr;
    unsigned 	nsymbols;
    pdvector<Symbol> allSymbols;
    pdvector<Address> all_addr(9, 0);
    pdvector<long> all_size(9, 0);
    pdvector<bool> all_dex(9, false);
    pdvector<long> all_disk(9, 0);

        if (!(ldptr = ldopen(file, ldptr))) {
            log_perror(err_func_, file);
	    success = false;
	    bperr("failed open\n");
	    free(file);
	    return;
        }
        did_open = true;

	if (TYPE(ldptr) != ALPHAMAGIC) {
	    bperr( "%s is not an alpha executable\n", file);
	    success = false;
	    bperr("failed magic region\n");
	    ldclose(ldptr);
	    free(file);
	    return;
        }

	// Read the text and data sections
	fhdr = HEADER(ldptr);
	unsigned short fmax = fhdr.f_nscns;

	dynamicallyLinked = false;

	// Life would be so much easier if there were a guaranteed order for
	// these sections.  But the man page makes no mention of it.
	while (sectindex < fmax) {
	  if (ldshread(ldptr, sectindex, &secthead) == SUCCESS) {
	    // cout << "Section: " << secthead.s_name << "\tStart: " << secthead.s_vaddr 
	    // << "\tEnd: " << secthead.s_vaddr + secthead.s_size << endl;

	    if (!P_strcmp(secthead.s_name, ".text")) {
	      code_len_ = (Word) secthead.s_size;
	      Word *buffer = new Word[code_len_+1];
	      code_ptr_ = buffer;
	      code_off_ = (Address) secthead.s_vaddr;
	      if (!obj_read_section(secthead, ldptr, buffer)) {
		success = false;
		bperr("failed text region\n");
		ldclose(ldptr);
		free(file);
		return;
	      }
	      text_read = true;
	    } else if (!P_strcmp(secthead.s_name, ".data")) {
	      if (secthead.s_vaddr && secthead.s_scnptr) {
		all_addr[K_D_INDEX] = secthead.s_vaddr;
		all_size[K_D_INDEX] = secthead.s_size;
		all_dex[K_D_INDEX] = true;
		all_disk[K_D_INDEX] = secthead.s_scnptr;
	      } else {
		bperr("failed data region\n");
		success = false;
		ldclose(ldptr);
		free(file);
		return;
	      }
	    } else if (!P_strcmp(secthead.s_name, ".xdata")) {
	      if (secthead.s_vaddr && secthead.s_scnptr) {
		all_addr[K_XD_INDEX] = secthead.s_vaddr;
		all_size[K_XD_INDEX] = secthead.s_size;
		all_dex[K_XD_INDEX] = true;
		all_disk[K_XD_INDEX] = secthead.s_scnptr;
	      }
	    } else if (!P_strcmp(secthead.s_name, ".sdata")) {
	      if (secthead.s_vaddr && secthead.s_scnptr) {
		all_addr[K_SD_INDEX] = secthead.s_vaddr;
		all_size[K_SD_INDEX] = secthead.s_size;
		all_dex[K_SD_INDEX] = true;
		all_disk[K_SD_INDEX] = secthead.s_scnptr;
	      }
	    } else if (!P_strcmp(secthead.s_name, ".rdata")) {
	      if (secthead.s_vaddr && secthead.s_scnptr) {
		all_addr[K_RD_INDEX] = secthead.s_vaddr;
		all_size[K_RD_INDEX] = secthead.s_size;
		all_dex[K_RD_INDEX] = true;
		all_disk[K_RD_INDEX] = secthead.s_scnptr;
	      }
	    } else if (!P_strcmp(secthead.s_name, ".lit4")) {
	      if (secthead.s_vaddr && secthead.s_scnptr) {
		all_addr[K_L4_INDEX] = secthead.s_vaddr;
		all_size[K_L4_INDEX] = secthead.s_size;
		all_dex[K_L4_INDEX] = true;
		all_disk[K_L4_INDEX] = secthead.s_scnptr;
	      }
	    } else if (!P_strcmp(secthead.s_name, ".lita")) {
	      if (secthead.s_vaddr && secthead.s_scnptr) {
		all_addr[K_LA_INDEX] = secthead.s_vaddr;
		all_size[K_LA_INDEX] = secthead.s_size;
		all_dex[K_LA_INDEX] = true;
		all_disk[K_LA_INDEX] = secthead.s_scnptr;
	      }
	    } else if (!P_strcmp(secthead.s_name, ".rconst")) {
	      if (secthead.s_vaddr && secthead.s_scnptr) {
		all_addr[K_RC_INDEX] = secthead.s_vaddr;
		all_size[K_RC_INDEX] = secthead.s_size;
		all_dex[K_RC_INDEX] = true;
		all_disk[K_RC_INDEX] = secthead.s_scnptr;
	      }
	    } else if (!P_strcmp(secthead.s_name, ".lit8")) {
	      if (secthead.s_vaddr && secthead.s_scnptr) {
		all_addr[K_L8_INDEX] = secthead.s_vaddr;
		all_size[K_L8_INDEX] = secthead.s_size;
		all_dex[K_L8_INDEX] = true;
		all_disk[K_L8_INDEX] = secthead.s_scnptr;
	      }
	    } else if (!P_strncmp(secthead.s_name, ".dynamic", 8)) {
	      // a section .dynamic implies the program is dynamically linked
	      dynamicallyLinked = true; 
	    }
	  } else {
	    success = false;
	    bperr("failed header region\n");
	    ldclose(ldptr);
	    free(file);
	    return;
	  }
	  sectindex++;
	}

	if (!text_read) { 
	  success = false;
	  bperr("failed text region\n");
	  ldclose(ldptr);
	  free(file);
	  return;
	}

	// I am assuming that .data comes before all other data sections
	// I will include all other contiguous data sections
	// Determine the size of the data section(s)
	if (all_disk[K_D_INDEX]) {
	    if (!find_data_region(all_addr, all_size, all_disk,
                                  data_len_, data_off_)) {
	      success = false;
	      bperr("failed find data region\n");
	      ldclose(ldptr);
	      free(file);
	      return;
	    }
	}

	// Now read in the data from the assorted data regions
	Word *buffer = new Word[data_len_+1];
	data_ptr_ = buffer;
	if (!read_data_region(all_addr, all_size, all_disk,
			      data_len_, data_off_, buffer, ldptr)) {
	  success = false;
          bperr("failed read data region\n");
	  ldclose(ldptr);
	  free(file);
	  return;
	}

	// COFF doesn't have segments, so the entire code/data sections are valid
	code_vldS_ = code_off_;
	code_vldE_ = code_off_ + code_len_;
	data_vldS_ = data_off_;
	data_vldE_ = data_off_ + code_len_;

        // Check for the symbol table
	if (!(sym_tab_ptr = PSYMTAB(ldptr))) {
	    success = false;
            bperr("failed check for symbol table - object may be strip'd!\n");
	    ldclose(ldptr);
	    free(file);
	    return;
	}

	// Read the symbol table
	sym_hdr = SYMHEADER(ldptr);
	if (sym_hdr.magic != magicSym) {
	    success = false;
            bperr("failed check for magic symbol\n");
	    ldclose(ldptr);
	    free(file);
	    return;
        }
	if (!(sym_tab_ptr = SYMTAB(ldptr))) {
	    success = false;
            bperr("failed read symbol table\n");
	    ldclose(ldptr);
	    free(file);
	    return;
	}
	if (LDSWAP(ldptr)) {
	  // These bytes are swapped
	  // supposedly libsex.a will unswap them
	  assert(0);
	}

	pdstring module = "DEFAULT_MODULE";
   if (sharedLibrary) {
      module = file_;
      allSymbols.push_back(Symbol(module, module, Symbol::PDST_MODULE, 
                                  Symbol::SL_GLOBAL, (Address) 0, false));
	} else {
      module = "DEFAULT_MODULE";
	}

   pdstring name = "DEFAULT_SYMBOL";
	int moduleEndIdx = -1;
	dictionary_hash<pdstring, int> fcnNames(pdstring::hash);

	while (ldtbread(ldptr, index, &symbol) == SUCCESS) {
	  // TODO -- when global?
	  Symbol::SymbolLinkage linkage = Symbol::SL_GLOBAL;
	  Symbol::SymbolType type = Symbol::PDST_UNKNOWN;
	  bool st_kludge = false;
	  bool sym_use = true;
	  char *name = ldgetname(ldptr, &symbol);
	  char prettyName[1024];

	switch(symbol.st) {
	case stProc:
	case stStaticProc:
		// Native C++ name demangling.
		MLD_demangle_string(name, prettyName, 1024,
				    MLD_SHOW_DEMANGLED_NAME | MLD_NO_SPACES);
		if (strchr(prettyName, '('))
		    *strchr(prettyName, '(') = 0;
		name = prettyName;

		if (symbol.sc == scText && !fcnNames.defines(name)) {
			type = Symbol::PDST_FUNCTION;
			fcnNames[name] = 1;
		}
		else 
			sym_use = false;
		break;

	case stGlobal:
	case stConstant:
	case stStatic:
		switch(symbol.sc) {
		case scData:
		case scSData:
		case scBss:
		case scSBss:
		case scRData:
		case scRConst:
		case scTlsData:
		case scTlsBss:
			type = Symbol::PDST_OBJECT;
			break;
		default:
			sym_use = false;
		}
		break;

	case stLocal:
	case stParam:
		linkage = Symbol::SL_LOCAL;

		switch(symbol.sc) {
		case scAbs:
		case scRegister:
		case scVar:
		case scVarRegister:
		case scUnallocated:
			type = Symbol::PDST_OBJECT;
			break;

		case scData:
		case scSData:
		case scBss:
		case scSBss:
		case scRConst:
		case scRData:
			 //Parameter is static var. Don't know what to do
			if (symbol.st == stParam)
				type = Symbol::PDST_OBJECT;
			else
				sym_use = false;
			break;

		default:
			sym_use = false;
		}
		break;

	case stTypedef:
	case stBase: //Base class
	case stTag: //C++ class, structure or union
		if (symbol.sc == scInfo)
			type = Symbol::PDST_OBJECT;
		else
			sym_use = false;
		break;

	case stFile:
		if (!sharedLibrary) {
			module = ldgetname(ldptr, &symbol); assert(module.length());
			type   = Symbol::PDST_MODULE;
			moduleEndIdx = symbol.index - 1;
			//Detect the compiler type by searching libgcc.
			if (strstr(module.c_str(), "libgcc"))
				GCC_COMPILED = true;
		}
		break;

	case stLabel:
		// For stLabel/scText combinations, if the symbol address falls
		// within the text section and has a valid name, process it as
		// a function.
		if (symbol.sc == scText &&
		    code_vldS_ <= (unsigned) symbol.value && (unsigned) symbol.value < code_vldE_ &&
		    name && *name && !fcnNames.defines(name)) {
			// Native C++ name demangling.
		        // Keep this in sync with stProc case above.

			MLD_demangle_string(name, prettyName, 1024,
					    MLD_SHOW_DEMANGLED_NAME | MLD_NO_SPACES);
			if (strchr(prettyName, '('))
			    *strchr(prettyName, '(') = 0;
			name = prettyName;

			type = Symbol::PDST_FUNCTION;
			fcnNames[name] = 1;

		} else {
			sym_use = false;
		}
		break;

	case stEnd:
		if (index == moduleEndIdx)
			module = "DEFAULT_MODULE";
		sym_use = false;
		break;

	default:
		sym_use = false;
	}

	// Skip eCoff encoded stab string.  Functions and global variable
	// addresses will still be found via the external symbols.
	if (P_strchr(name, ':'))
	    sym_use = false;
	
	// cout << index << "\t" << name << "\t" << StName(symbol.st) << "\t" << ScName(symbol.sc) << "\t" << symbol.value << "\n";

	  index++;

	  if (sym_use) {
	    // cout << index << "\t" << module << "\t" << name << "\t" << type << "\t" << symbol.value << "\n";
	    allSymbols.push_back(Symbol(name, module, type, linkage,
				      (Address) symbol.value, st_kludge));
	  }

    } //while

    VECTOR_SORT(allSymbols,symbol_compare);
    // find the function boundaries
    nsymbols = allSymbols.size();

    //Insert global symbols
    for (unsigned u = 0; u < nsymbols; u++) {
	unsigned size = 0;
	if (allSymbols[u].type() == Symbol::PDST_FUNCTION) {
	    unsigned v = u+1;
	    while (v < nsymbols) {
		// The .ef below is a special symbol that gcc puts in to
                // mark the end of a function.
                if (allSymbols[v].addr() != allSymbols[u].addr() &&
                      (allSymbols[v].type() == Symbol::PDST_FUNCTION ||
                       allSymbols[v].name() == ".ef"))
                break;
                v++;
            }
	    if (v < nsymbols) {
                  size = (unsigned)allSymbols[v].addr()
                         - (unsigned)allSymbols[u].addr();
	    } else {
                size = (unsigned)(code_off_+code_len_)
                         - (unsigned)allSymbols[u].addr();
	    }
	}
	
	if (allSymbols[u].linkage() != Symbol::SL_LOCAL) {
		symbols_[allSymbols[u].name()].push_back( 
	   		Symbol(allSymbols[u].name(), allSymbols[u].module(), 
	      		allSymbols[u].type(), allSymbols[u].linkage(), 
	       		allSymbols[u].addr(), allSymbols[u].kludge(), size) ); 
	}
    }

    //Insert local symbols (Do we need this?)
    for (unsigned u = 0; u < nsymbols; u++) {
	if ( (allSymbols[u].linkage() == Symbol::SL_LOCAL) &&
		(!symbols_.defines(allSymbols[u].name())) ) {
		symbols_[allSymbols[u].name()].push_back( 
	   		Symbol(allSymbols[u].name(), allSymbols[u].module(), 
	      		allSymbols[u].type(), allSymbols[u].linkage(), 
	       		allSymbols[u].addr(), allSymbols[u].kludge(), 0) );
	}
    }
		
    if (did_open && (ldclose(ldptr) == FAILURE)) {
        log_perror(err_func_, "close");
    }
    free(file);

}