chk4ubin.c revision b31b5de1357c915fe7dab4d9646d9d84f9fe69bc
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include <stdlib.h>
#include <errno.h>
#include <malloc.h>
#include <memory.h>
#include <libelf.h>
#include <gelf.h>
#include <utility.h>
/*
* Tool to inspect a sun4u bootable module for a symbol table size
* that will trigger a fatal error on older versions of OBP.
*
* The failure mode when booting is recorded in CR 6828121
* and appears as follows:
*
* Executing last command: boot
* Boot device: /pci@1f,0/pci@1/scsi@8/disk@0,0:a File and args: kmdb
*
* Error in Fcode execution !!!
* Evaluating: to load-base init-program
* Out of memory
* Warning: Fcode sequence resulted in a net stack depth change of 1
*
* Error in Fcode execution !!!
* Evaluating: to load-base init-program
*
* Evaluating: to load-base init-program
* The file just loaded does not appear to be executable.
* ok
*
* The OBP bug is CR 4777088, fixed in OBP versions 4.12.1 and forward.
*
* The OBP memory allocator for the memory into which the module's
* symbol table is read fails for a specific memory range on
* each page, where the size &= 0x1fff is > 0x1fe1 && <= 0x1ff0.
* Note the symbol table size is the size of both the SYMTAB
* and the STRTAB ELF sections.
*
* To prevent this problem on a given machine, update or patch the OBP.
*
* If this tool reports that a module has a symbol table size in
* the failing range, that build will not boot on any machine with
* this OBP problem. The only known work-around is to make some
* source change to add or remove symbols to adjust the symbol table
* size outside the triggering range.
*
* Each sun4u bootable module is in theory affected by this, including
* cprboot, bootlst, and each unix module. Although the serengeti
* (Sun-Fire) and opl (SPARC-Enterprise) OBP implementations never
* included this bug. The bug only occurs for allocations
* pagesize or greater, and the only such OBP allocation is for a
* module's symbol table, for the sum of the SYMTAB and STRTAB
* sections. The wanboot and inetboot binaries do not include
* these sections and are therefore also unaffected.
*/
static char *whoami;
static int verbose = 0;
static int inject_err = 0;
static int no_err = 0;
static int exitcode = 0;
static char *sun4u_bootables[] = {
};
static int nsun4ubootables = sizeof (sun4u_bootables) / sizeof (char *);
/*
* size check should be:
* size &= 0x1fff, size > 0x1fe1 && size <= 0x1ff0
*/
/*
* Tag each error message so it shows up in the build summary mail
*/
static char *detailed_error_msg =
"ERROR: This binary will not boot on any machine with an older\n"
"ERROR: version of OBP. See CR 4777088 and 6828121 for more details.\n"
"ERROR: No work-around is possible other than making changes to\n"
"ERROR: table size outside the toxic range.\n";
static int
{
int fd;
int found_symtab = 0;
int found_strtab = 0;
int rv = 1;
char path[MAXPATHLEN];
} else {
}
(void) printf("%s: cannot open %s - %s\n",
return (1);
}
case SHT_SYMTAB:
found_symtab = 1;
found_strtab = 1;
}
break;
}
if (found_symtab && found_strtab)
break;
}
if (found_symtab && found_strtab) {
int err;
if (inject_err || err) {
(void) printf("ERROR: symbol table size 0x%llx is "
"in toxic range (0x%x - 0x%x)!\n",
} else {
rv = 0;
if (verbose) {
(void) printf("symbol table size 0x%llx "
"not in toxic range (0x%x - 0x%x)\n",
}
}
if (verbose) {
(void) printf(".symtab size: 0x%llx\n",
(void) printf(".strtab size: 0x%llx\n",
(void) printf("total: 0x%llx "
}
(void) printf("\n");
} else {
if (!found_symtab && !found_strtab) {
"%s: %s - no symtab or strtab section found\n",
} else if (!found_symtab) {
"%s: %s - no symtab section found\n",
} else if (!found_strtab) {
"%s: %s - no strtab section found\n",
}
}
return (rv);
}
static void
usage()
{
int i;
"usage: %s [-n] [-v] [-r <root>] [<binary>] ...\n", whoami);
" -n: exit with 0 even with an error detected to allow\n");
" a build to succeed even with a failing binary\n");
"The default list of binaries checked if none supplied is:\n");
for (i = 0; i < nsun4ubootables; i++) {
}
exit(0);
}
int
{
int i;
opterr = 0;
switch (i) {
case 'v':
verbose = 1;
break;
case 'e':
inject_err = 1;
break;
case 'n':
no_err = 1;
break;
case 'r':
case 'R':
break;
default:
usage();
break;
}
}
exitcode = 1;
}
} else {
for (i = 0; i < nsun4ubootables; i++) {
root = "/";
exitcode = 1;
}
}
}