crash/configure.c

1948 lines
52 KiB
C

/* configure.c - core analysis suite
*
* Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
* Copyright (C) 2002-2013 David Anderson
* Copyright (C) 2002-2013 Red Hat, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/*
* define, clear and undef dynamically update the top-level Makefile:
*
* -b define: TARGET, GDB, GDB_FILES, GDB_OFILES, GDB_PATCH_FILES,
* TARGET_CFLAGS, LDFLAGS, GDB_CONF_FLAGS and GPL_FILES
* create: build_data.c
*
* -d define: TARGET, GDB, GDB_FILES, GDB_OFILES, GDB_PATCH_FILES,
* TARGET_CFLAGS, LDFLAGS, GDB_CONF_FLAGS and PROGRAM (for daemon)
* create: build_data.c
*
* -u clear: TARGET, GDB, GDB_FILES, GDB_OFILES, VERSION, GDB_PATCH_FILES,
* TARGET_CFLAGS, LDFLAGS, GDB_CONF_FLAGS and GPL_FILES
* undef: WARNING_ERROR, WARNING_OPTIONS
*
* -r define: GDB_FILES, VERSION, GDB_PATCH_FILES GPL_FILES
*
* -w define: WARNING_OPTIONS
* undef: WARNING_ERROR
*
* -W define: WARNING_ERROR, WARNING_OPTIONS
*
* -n undef: WARNING_ERROR, WARNING_OPTIONS
*
* -g define: GDB
*
* -p Create or remove .rh_rpm_package file
*
* -q Don't print configuration
*
* -s Create crash.spec file
*
* -x Add extra libraries/flags to build
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
struct supported_gdb_version;
void build_configure(struct supported_gdb_version *);
void release_configure(char *, struct supported_gdb_version *);
void make_rh_rpm_package(char *, int);
void unconfigure(void);
void set_warnings(int);
void show_configuration(void);
void target_rebuild_instructions(struct supported_gdb_version *, char *);
void arch_mismatch(struct supported_gdb_version *);
void get_current_configuration(struct supported_gdb_version *);
void makefile_setup(FILE **, FILE **);
void makefile_create(FILE **, FILE **);
char *strip_linefeeds(char *);
char *upper_case(char *, char *);
char *lower_case(char *, char *);
char *shift_string_left(char *, int);
char *shift_string_right(char *, int);
char *strip_beginning_whitespace(char *);
char *strip_ending_whitespace(char *);
char *strip_linefeeds(char *);
int file_exists(char *);
int count_chars(char *, char);
void make_build_data(char *);
void gdb_configure(struct supported_gdb_version *);
int parse_line(char *, char **);
struct supported_gdb_version *setup_gdb_defaults(void);
struct supported_gdb_version *store_gdb_defaults(struct supported_gdb_version *);
void make_spec_file(struct supported_gdb_version *);
void set_initial_target(struct supported_gdb_version *);
char *target_to_name(int);
int name_to_target(char *);
char *get_extra_flags(char *, char *);
void add_extra_lib(char *);
#define TRUE 1
#define FALSE 0
#undef X86
#undef ALPHA
#undef PPC
#undef IA64
#undef S390
#undef S390X
#undef PPC64
#undef X86_64
#undef ARM
#undef ARM64
#undef MIPS
#undef SPARC64
#undef MIPS64
#undef RISCV64
#undef LOONGARCH64
#define UNKNOWN 0
#define X86 1
#define ALPHA 2
#define PPC 3
#define IA64 4
#define S390 5
#define S390X 6
#define PPC64 7
#define X86_64 8
#define ARM 9
#define ARM64 10
#define MIPS 11
#define SPARC64 12
#define MIPS64 13
#define RISCV64 14
#define LOONGARCH64 15
#define TARGET_X86 "TARGET=X86"
#define TARGET_ALPHA "TARGET=ALPHA"
#define TARGET_PPC "TARGET=PPC"
#define TARGET_IA64 "TARGET=IA64"
#define TARGET_S390 "TARGET=S390"
#define TARGET_S390X "TARGET=S390X"
#define TARGET_PPC64 "TARGET=PPC64"
#define TARGET_X86_64 "TARGET=X86_64"
#define TARGET_ARM "TARGET=ARM"
#define TARGET_ARM64 "TARGET=ARM64"
#define TARGET_MIPS "TARGET=MIPS"
#define TARGET_MIPS64 "TARGET=MIPS64"
#define TARGET_SPARC64 "TARGET=SPARC64"
#define TARGET_RISCV64 "TARGET=RISCV64"
#define TARGET_LOONGARCH64 "TARGET=LOONGARCH64"
#define TARGET_CFLAGS_X86 "TARGET_CFLAGS=-D_FILE_OFFSET_BITS=64"
#define TARGET_CFLAGS_ALPHA "TARGET_CFLAGS="
#define TARGET_CFLAGS_PPC "TARGET_CFLAGS=-D_FILE_OFFSET_BITS=64"
#define TARGET_CFLAGS_IA64 "TARGET_CFLAGS="
#define TARGET_CFLAGS_S390 "TARGET_CFLAGS=-D_FILE_OFFSET_BITS=64"
#define TARGET_CFLAGS_S390X "TARGET_CFLAGS="
#define TARGET_CFLAGS_PPC64 "TARGET_CFLAGS=-m64"
#define TARGET_CFLAGS_X86_64 "TARGET_CFLAGS="
#define TARGET_CFLAGS_ARM "TARGET_CFLAGS=-D_FILE_OFFSET_BITS=64"
#define TARGET_CFLAGS_ARM_ON_X86 "TARGET_CFLAGS=-D_FILE_OFFSET_BITS=64"
#define TARGET_CFLAGS_ARM_ON_X86_64 "TARGET_CFLAGS=-m32 -D_FILE_OFFSET_BITS=64"
#define TARGET_CFLAGS_X86_ON_X86_64 "TARGET_CFLAGS=-m32 -D_FILE_OFFSET_BITS=64"
#define TARGET_CFLAGS_PPC_ON_PPC64 "TARGET_CFLAGS=-m32 -D_FILE_OFFSET_BITS=64 -fPIC"
#define TARGET_CFLAGS_ARM64 "TARGET_CFLAGS="
#define TARGET_CFLAGS_ARM64_ON_X86_64 "TARGET_CFLAGS="
#define TARGET_CFLAGS_PPC64_ON_X86_64 "TARGET_CFLAGS="
#define TARGET_CFLAGS_MIPS "TARGET_CFLAGS=-D_FILE_OFFSET_BITS=64"
#define TARGET_CFLAGS_MIPS_ON_X86 "TARGET_CFLAGS=-D_FILE_OFFSET_BITS=64"
#define TARGET_CFLAGS_MIPS_ON_X86_64 "TARGET_CFLAGS=-m32 -D_FILE_OFFSET_BITS=64"
#define TARGET_CFLAGS_MIPS64 "TARGET_CFLAGS="
#define TARGET_CFLAGS_SPARC64 "TARGET_CFLAGS="
#define TARGET_CFLAGS_RISCV64 "TARGET_CFLAGS="
#define TARGET_CFLAGS_RISCV64_ON_X86_64 "TARGET_CFLAGS="
#define TARGET_CFLAGS_LOONGARCH64 "TARGET_CFLAGS="
#define TARGET_CFLAGS_LOONGARCH64_ON_X86_64 "TARGET_CFLAGS="
#define GDB_TARGET_DEFAULT "GDB_CONF_FLAGS="
#define GDB_TARGET_ARM_ON_X86 "GDB_CONF_FLAGS=--target=arm-elf-linux"
#define GDB_TARGET_ARM_ON_X86_64 "GDB_CONF_FLAGS=--target=arm-elf-linux CFLAGS=-m32 CXXFLAGS=-m32"
#define GDB_TARGET_X86_ON_X86_64 "GDB_CONF_FLAGS=--target=i686-pc-linux-gnu CFLAGS=-m32 CXXFLAGS=-m32"
#define GDB_TARGET_PPC_ON_PPC64 "GDB_CONF_FLAGS=--target=ppc-elf-linux CFLAGS=-m32 CXXFLAGS=-m32"
#define GDB_TARGET_ARM64_ON_X86_64 "GDB_CONF_FLAGS=--target=aarch64-elf-linux" /* TBD */
#define GDB_TARGET_PPC64_ON_X86_64 "GDB_CONF_FLAGS=--target=powerpc64le-unknown-linux-gnu"
#define GDB_TARGET_MIPS_ON_X86 "GDB_CONF_FLAGS=--target=mipsel-elf-linux"
#define GDB_TARGET_MIPS_ON_X86_64 "GDB_CONF_FLAGS=--target=mipsel-elf-linux CFLAGS=-m32 CXXFLAGS=-m32"
#define GDB_TARGET_RISCV64_ON_X86_64 "GDB_CONF_FLAGS=--target=riscv64-unknown-linux-gnu"
#define GDB_TARGET_LOONGARCH64_ON_X86_64 "GDB_CONF_FLAGS=--target=loongarch64-unknown-linux-gnu"
/*
* The original plan was to allow the use of a particular version
* of gdb for a given architecture. But for practical purposes,
* it's a one-size-fits-all scheme, and they all use the default
* unless overridden.
*/
#define GDB_5_3 (0)
#define GDB_6_0 (1)
#define GDB_6_1 (2)
#define GDB_7_0 (3)
#define GDB_7_3_1 (4)
#define GDB_7_6 (5)
#define GDB_10_2 (6)
#define SUPPORTED_GDB_VERSIONS (GDB_10_2 + 1)
int default_gdb = GDB_10_2;
struct supported_gdb_version {
char *GDB;
char *GDB_VERSION_IN;
char *GDB_FILES;
char *GDB_OFILES;
char *GDB_PATCH_FILES;
char *GDB_FLAGS;
char *GPL;
} supported_gdb_versions[SUPPORTED_GDB_VERSIONS] = {
{
"GDB=gdb-5.3post-0.20021129.36rh",
"Red Hat Linux (5.3post-0.20021129.36rh)",
"GDB_FILES=${GDB_5.3post-0.20021129.36rh_FILES}",
"GDB_OFILES=${GDB_5.3post-0.20021129.36rh_OFILES}",
"GDB_PATCH_FILES=",
"GDB_FLAGS=-DGDB_5_3",
"GPLv2"
},
{
"GDB=gdb-6.0",
"6.0",
"GDB_FILES=${GDB_6.0_FILES}",
"GDB_OFILES=${GDB_6.0_OFILES}",
"GDB_PATCH_FILES=",
"GDB_FLAGS=-DGDB_6_0",
"GPLv2"
},
{
"GDB=gdb-6.1",
"6.1",
"GDB_FILES=${GDB_6.1_FILES}",
"GDB_OFILES=${GDB_6.1_OFILES}",
"GDB_PATCH_FILES=gdb-6.1.patch",
"GDB_FLAGS=-DGDB_6_1",
"GPLv2"
},
{
"GDB=gdb-7.0",
"7.0",
"GDB_FILES=${GDB_7.0_FILES}",
"GDB_OFILES=${GDB_7.0_OFILES}",
"GDB_PATCH_FILES=gdb-7.0.patch",
"GDB_FLAGS=-DGDB_7_0",
"GPLv3"
},
{
"GDB=gdb-7.3.1",
"7.3.1",
"GDB_FILES=${GDB_7.3.1_FILES}",
"GDB_OFILES=${GDB_7.3.1_OFILES}",
"GDB_PATCH_FILES=gdb-7.3.1.patch",
"GDB_FLAGS=-DGDB_7_3_1",
"GPLv3"
},
{
"GDB=gdb-7.6",
"7.6",
"GDB_FILES=${GDB_7.6_FILES}",
"GDB_OFILES=${GDB_7.6_OFILES}",
"GDB_PATCH_FILES=gdb-7.6.patch gdb-7.6-ppc64le-support.patch gdb-7.6-proc_service.h.patch",
"GDB_FLAGS=-DGDB_7_6",
"GPLv3"
},
{
"GDB=gdb-10.2",
"10.2",
"GDB_FILES=${GDB_10.2_FILES}",
"GDB_OFILES=${GDB_10.2_OFILES}",
"GDB_PATCH_FILES=gdb-10.2.patch",
"GDB_FLAGS=-DGDB_10_2",
"GPLv3"
},
};
#define DAEMON 0x1
#define QUIET 0x2
#define MAXSTRLEN 256
#define MIN(a,b) (((a)<(b))?(a):(b))
struct target_data {
int target;
int host;
int initial_gdb_target;
int flags;
char program[MAXSTRLEN];
char gdb_version[MAXSTRLEN];
char release[MAXSTRLEN];
struct stat statbuf;
const char *target_as_param;
} target_data = { 0 };
int
main(int argc, char **argv)
{
int c;
struct supported_gdb_version *sp;
sp = setup_gdb_defaults();
while ((c = getopt(argc, argv, "gsqnWwubdr:p:P:t:x:")) > 0) {
switch (c) {
case 'q':
target_data.flags |= QUIET;
break;
case 'u':
unconfigure();
break;
case 'd':
target_data.flags |= DAEMON;
case 'b':
build_configure(sp);
break;
case 'r':
release_configure(optarg, sp);
break;
case 'p':
make_rh_rpm_package(optarg, 0);
break;
case 'P':
make_rh_rpm_package(optarg, 1);
break;
case 'W':
case 'w':
case 'n':
set_warnings(c);
break;
case 's':
make_spec_file(sp);
break;
case 'g':
gdb_configure(sp);
break;
case 't':
target_data.target_as_param = optarg;
break;
case 'x':
add_extra_lib(optarg);
break;
}
}
exit(0);
}
void
target_rebuild_instructions(struct supported_gdb_version *sp, char *target)
{
fprintf(stderr,
"\nIn order to build a crash binary for the %s architecture:\n",
target);
fprintf(stderr, " 1. remove the %s subdirectory\n",
&sp->GDB[strlen("GDB=")]);
fprintf(stderr, " 2. perform a \"make clean\"\n");
fprintf(stderr, " 3. retry the build\n\n");
}
void
arch_mismatch(struct supported_gdb_version *sp)
{
fprintf(stderr,
"\nThe initial build in this source tree was for the %s architecture.\n",
target_to_name(target_data.initial_gdb_target));
target_rebuild_instructions(sp, target_to_name(target_data.target));
exit(1);
}
void
get_current_configuration(struct supported_gdb_version *sp)
{
FILE *fp;
static char buf[512];
char *p;
#ifdef __alpha__
target_data.target = ALPHA;
#endif
#ifdef __i386__
target_data.target = X86;
#endif
#ifdef __powerpc__
target_data.target = PPC;
#endif
#ifdef __ia64__
target_data.target = IA64;
#endif
#ifdef __s390__
target_data.target = S390;
#endif
#ifdef __s390x__
target_data.target = S390X;
#endif
#ifdef __powerpc64__
target_data.target = PPC64;
#endif
#ifdef __x86_64__
target_data.target = X86_64;
#endif
#ifdef __arm__
target_data.target = ARM;
#endif
#ifdef __aarch64__
target_data.target = ARM64;
#endif
#ifdef __mips__
#ifndef __mips64
target_data.target = MIPS;
#else
target_data.target = MIPS64;
#endif
#endif
#ifdef __sparc_v9__
target_data.target = SPARC64;
#endif
#if defined(__riscv) && (__riscv_xlen == 64)
target_data.target = RISCV64;
#endif
#ifdef __loongarch64
target_data.target = LOONGARCH64;
#endif
set_initial_target(sp);
/*
* Override target if specified on command line.
*/
target_data.host = target_data.target;
if (target_data.target_as_param) {
if ((target_data.target == X86 || target_data.target == X86_64) &&
(name_to_target((char *)target_data.target_as_param) == ARM)) {
/*
* Debugging of ARM core files supported on X86, and on
* X86_64 when built as a 32-bit executable.
*/
target_data.target = ARM;
} else if ((target_data.target == X86 || target_data.target == X86_64) &&
(name_to_target((char *)target_data.target_as_param) == MIPS)) {
/*
* Debugging of MIPS little-endian core files
* supported on X86, and on X86_64 when built as a
* 32-bit executable.
*/
target_data.target = MIPS;
} else if ((target_data.target == X86_64) &&
(name_to_target((char *)target_data.target_as_param) == X86)) {
/*
* Build an X86 crash binary on an X86_64 host.
*/
target_data.target = X86;
} else if ((target_data.target == X86_64) &&
(name_to_target((char *)target_data.target_as_param) == ARM64)) {
/*
* Build an ARM64 crash binary on an X86_64 host.
*/
target_data.target = ARM64;
} else if ((target_data.target == X86_64) &&
(name_to_target((char *)target_data.target_as_param) == PPC64)) {
/*
* Build a PPC64 little-endian crash binary on an X86_64 host.
*/
target_data.target = PPC64;
} else if ((target_data.target == PPC64) &&
(name_to_target((char *)target_data.target_as_param) == PPC)) {
/*
* Build an PPC crash binary on an PPC64 host.
*/
target_data.target = PPC;
} else if (name_to_target((char *)target_data.target_as_param) ==
target_data.host) {
if ((target_data.initial_gdb_target != UNKNOWN) &&
(target_data.host != target_data.initial_gdb_target))
arch_mismatch(sp);
} else if ((target_data.target == X86_64) &&
(name_to_target((char *)target_data.target_as_param) == RISCV64)) {
/*
* Build an RISCV64 crash binary on an X86_64 host.
*/
target_data.target = RISCV64;
} else if ((target_data.target == X86_64) &&
(name_to_target((char *)target_data.target_as_param) == LOONGARCH64)) {
/*
* Build an LOONGARCH64 crash binary on an X86_64 host.
*/
target_data.target = LOONGARCH64;
} else {
fprintf(stderr,
"\ntarget=%s is not supported on the %s host architecture\n\n",
target_data.target_as_param,
target_to_name(target_data.host));
exit(1);
}
}
/*
* Impose implied (sticky) target if an initial build has been
* done in the source tree.
*/
if (target_data.initial_gdb_target &&
(target_data.target != target_data.initial_gdb_target)) {
if ((target_data.initial_gdb_target == ARM) &&
(target_data.target != ARM)) {
if ((target_data.target == X86) ||
(target_data.target == X86_64))
target_data.target = ARM;
else
arch_mismatch(sp);
}
if ((target_data.target == ARM) &&
(target_data.initial_gdb_target != ARM))
arch_mismatch(sp);
if ((target_data.initial_gdb_target == MIPS) &&
(target_data.target != MIPS)) {
if ((target_data.target == X86) ||
(target_data.target == X86_64))
target_data.target = MIPS;
else
arch_mismatch(sp);
}
if ((target_data.initial_gdb_target == MIPS64) &&
(target_data.target != MIPS64))
arch_mismatch(sp);
if ((target_data.initial_gdb_target == LOONGARCH64) &&
(target_data.target != LOONGARCH64)) {
if (target_data.target == X86_64)
target_data.target = LOONGARCH64;
else
arch_mismatch(sp);
}
if ((target_data.initial_gdb_target == RISCV64) &&
(target_data.target != RISCV64)) {
if (target_data.target == X86_64)
target_data.target = RISCV64;
else
arch_mismatch(sp);
}
if ((target_data.initial_gdb_target == X86) &&
(target_data.target != X86)) {
if (target_data.target == X86_64)
target_data.target = X86;
else
arch_mismatch(sp);
}
if ((target_data.target == X86) &&
(target_data.initial_gdb_target != X86))
arch_mismatch(sp);
if ((target_data.initial_gdb_target == ARM64) &&
(target_data.target != ARM64)) {
if (target_data.target == X86_64)
target_data.target = ARM64;
else
arch_mismatch(sp);
}
if ((target_data.target == ARM64) &&
(target_data.initial_gdb_target != ARM64))
arch_mismatch(sp);
if ((target_data.initial_gdb_target == PPC64) &&
(target_data.target != PPC64)) {
if (target_data.target == X86_64)
target_data.target = PPC64;
else
arch_mismatch(sp);
}
if ((target_data.target == PPC64) &&
(target_data.initial_gdb_target != PPC64))
arch_mismatch(sp);
if ((target_data.initial_gdb_target == PPC) &&
(target_data.target != PPC)) {
if (target_data.target == PPC64)
target_data.target = PPC;
else
arch_mismatch(sp);
}
if ((target_data.target == PPC) &&
(target_data.initial_gdb_target != PPC))
arch_mismatch(sp);
if ((target_data.target == SPARC64) &&
(target_data.initial_gdb_target != SPARC64))
arch_mismatch(sp);
}
if ((fp = fopen("Makefile", "r")) == NULL) {
perror("Makefile");
goto get_release;
}
while (fgets(buf, 512, fp)) {
if (strncmp(buf, "PROGRAM=", strlen("PROGRAM=")) == 0) {
p = strstr(buf, "=") + 1;
strip_linefeeds(p);
upper_case(p, target_data.program);
if (target_data.flags & DAEMON)
strcat(target_data.program, "D");
continue;
}
}
fclose(fp);
get_release:
target_data.release[0] = '\0';
if (file_exists(".rh_rpm_package")) {
if ((fp = fopen(".rh_rpm_package", "r")) == NULL) {
perror(".rh_rpm_package");
} else {
if (fgets(buf, 512, fp)) {
strip_linefeeds(buf);
if (strlen(buf)) {
buf[MAXSTRLEN-1] = '\0';
strcpy(target_data.release, buf);
} else
fprintf(stderr,
"WARNING: .rh_rpm_package file is empty!\n");
} else
fprintf(stderr,
"WARNING: .rh_rpm_package file is empty!\n");
fclose(fp);
if (strlen(target_data.release))
return;
}
} else
fprintf(stderr,
"WARNING: .rh_rpm_package file does not exist!\n");
if ((fp = fopen("defs.h", "r")) == NULL) {
perror("defs.h");
return;
}
while (fgets(buf, 512, fp)) {
if (strncmp(buf, "#define BASELEVEL_REVISION",
strlen("#define BASELEVEL_REVISION")) == 0) {
p = strstr(buf, "\"") + 1;
strip_linefeeds(p);
p[strlen(p)-1] = '\0';
strcpy(target_data.release, p);
break;
}
}
fclose(fp);
}
void
show_configuration(void)
{
int i;
if (target_data.flags & QUIET)
return;
switch (target_data.target)
{
case X86:
printf("TARGET: X86\n");
break;
case ALPHA:
printf("TARGET: ALPHA\n");
break;
case PPC:
printf("TARGET: PPC\n");
break;
case IA64:
printf("TARGET: IA64\n");
break;
case S390:
printf("TARGET: S390\n");
break;
case S390X:
printf("TARGET: S390X\n");
break;
case PPC64:
printf("TARGET: PPC64\n");
break;
case X86_64:
printf("TARGET: X86_64\n");
break;
case ARM:
printf("TARGET: ARM\n");
break;
case ARM64:
printf("TARGET: ARM64\n");
break;
case MIPS:
printf("TARGET: MIPS\n");
break;
case MIPS64:
printf("TARGET: MIPS64\n");
break;
case SPARC64:
printf("TARGET: SPARC64\n");
break;
case RISCV64:
printf("TARGET: RISCV64\n");
break;
case LOONGARCH64:
printf("TARGET: LOONGARCH64\n");
break;
}
if (strlen(target_data.program)) {
for (i = 0; i < (strlen("TARGET")-strlen(target_data.program));
i++)
printf(" ");
printf("%s: ", target_data.program);
if (strlen(target_data.release))
printf("%s\n", target_data.release);
else
printf("???\n");
}
if (strlen(target_data.gdb_version))
printf(" GDB: %s\n\n", &target_data.gdb_version[4]);
}
void
build_configure(struct supported_gdb_version *sp)
{
FILE *fp1, *fp2;
char buf[512];
char *target;
char *target_CFLAGS;
char *gdb_conf_flags;
char *ldflags;
char *cflags;
get_current_configuration(sp);
target = target_CFLAGS = NULL;
gdb_conf_flags = GDB_TARGET_DEFAULT;
switch (target_data.target)
{
case X86:
target = TARGET_X86;
if (target_data.host == X86_64) {
target_CFLAGS = TARGET_CFLAGS_X86_ON_X86_64;
gdb_conf_flags = GDB_TARGET_X86_ON_X86_64;
} else
target_CFLAGS = TARGET_CFLAGS_X86;
break;
case ALPHA:
target = TARGET_ALPHA;
target_CFLAGS = TARGET_CFLAGS_ALPHA;
break;
case PPC:
target = TARGET_PPC;
if (target_data.host == PPC64) {
target_CFLAGS = TARGET_CFLAGS_PPC_ON_PPC64;
gdb_conf_flags = GDB_TARGET_PPC_ON_PPC64;
} else
target_CFLAGS = TARGET_CFLAGS_PPC;
break;
case IA64:
target = TARGET_IA64;
target_CFLAGS = TARGET_CFLAGS_IA64;
break;
case S390:
target = TARGET_S390;
target_CFLAGS = TARGET_CFLAGS_S390;
break;
case S390X:
target = TARGET_S390X;
target_CFLAGS = TARGET_CFLAGS_S390X;
break;
case PPC64:
target = TARGET_PPC64;
if (target_data.host == X86_64) {
target_CFLAGS = TARGET_CFLAGS_PPC64_ON_X86_64;
gdb_conf_flags = GDB_TARGET_PPC64_ON_X86_64;
} else
target_CFLAGS = TARGET_CFLAGS_PPC64;
break;
case X86_64:
target = TARGET_X86_64;
target_CFLAGS = TARGET_CFLAGS_X86_64;
break;
case ARM:
target = TARGET_ARM;
if (target_data.host == X86) {
target_CFLAGS = TARGET_CFLAGS_ARM_ON_X86;
gdb_conf_flags = GDB_TARGET_ARM_ON_X86;
} else if (target_data.host == X86_64) {
target_CFLAGS = TARGET_CFLAGS_ARM_ON_X86_64;
gdb_conf_flags = GDB_TARGET_ARM_ON_X86_64;
} else
target_CFLAGS = TARGET_CFLAGS_ARM;
break;
case ARM64:
target = TARGET_ARM64;
if (target_data.host == X86_64) {
target_CFLAGS = TARGET_CFLAGS_ARM64_ON_X86_64;
gdb_conf_flags = GDB_TARGET_ARM64_ON_X86_64;
} else
target_CFLAGS = TARGET_CFLAGS_ARM64;
break;
case MIPS:
target = TARGET_MIPS;
if (target_data.host == X86) {
target_CFLAGS = TARGET_CFLAGS_MIPS_ON_X86;
gdb_conf_flags = GDB_TARGET_MIPS_ON_X86;
} else if (target_data.host == X86_64) {
target_CFLAGS = TARGET_CFLAGS_MIPS_ON_X86_64;
gdb_conf_flags = GDB_TARGET_MIPS_ON_X86_64;
} else
target_CFLAGS = TARGET_CFLAGS_MIPS;
break;
case MIPS64:
target = TARGET_MIPS64;
target_CFLAGS = TARGET_CFLAGS_MIPS64;
break;
case SPARC64:
target = TARGET_SPARC64;
target_CFLAGS = TARGET_CFLAGS_SPARC64;
break;
case RISCV64:
target = TARGET_RISCV64;
if (target_data.host == X86_64) {
target_CFLAGS = TARGET_CFLAGS_RISCV64_ON_X86_64;
gdb_conf_flags = GDB_TARGET_RISCV64_ON_X86_64;
} else
target_CFLAGS = TARGET_CFLAGS_RISCV64;
break;
case LOONGARCH64:
target = TARGET_LOONGARCH64;
if (target_data.host == X86_64) {
target_CFLAGS = TARGET_CFLAGS_LOONGARCH64_ON_X86_64;
gdb_conf_flags = GDB_TARGET_LOONGARCH64_ON_X86_64;
} else
target_CFLAGS = TARGET_CFLAGS_LOONGARCH64;
break;
}
ldflags = get_extra_flags("LDFLAGS.extra", NULL);
cflags = get_extra_flags("CFLAGS.extra", NULL);
gdb_conf_flags = get_extra_flags("GDBFLAGS.extra", gdb_conf_flags);
makefile_setup(&fp1, &fp2);
while (fgets(buf, 512, fp1)) {
if (strncmp(buf, "TARGET=", strlen("TARGET=")) == 0)
fprintf(fp2, "%s\n", target);
else if (strncmp(buf, "TARGET_CFLAGS=",
strlen("TARGET_CFLAGS=")) == 0)
fprintf(fp2, "%s%s%s\n", target_CFLAGS,
cflags ? " " : "", cflags ? cflags : "");
else if (strncmp(buf, "GDB_CONF_FLAGS=",
strlen("GDB_CONF_FLAGS=")) == 0)
fprintf(fp2, "%s\n", gdb_conf_flags);
else if (strncmp(buf, "GDB_FILES=",strlen("GDB_FILES=")) == 0)
fprintf(fp2, "%s\n", sp->GDB_FILES);
else if (strncmp(buf, "GDB_OFILES=",strlen("GDB_OFILES=")) == 0)
fprintf(fp2, "%s\n", sp->GDB_OFILES);
else if (strncmp(buf, "GDB_PATCH_FILES=",strlen("GDB_PATCH_FILES=")) == 0)
fprintf(fp2, "%s\n", sp->GDB_PATCH_FILES);
else if (strncmp(buf, "GDB_FLAGS=",strlen("GDB_FLAGS=")) == 0)
fprintf(fp2, "%s\n", sp->GDB_FLAGS);
else if (strncmp(buf, "GPL_FILES=", strlen("GPL_FILES=")) == 0)
fprintf(fp2, "GPL_FILES=%s\n", strcmp(sp->GPL, "GPLv2") == 0 ?
"COPYING" : "COPYING3");
else if (strncmp(buf, "GDB=", strlen("GDB=")) == 0) {
fprintf(fp2, "%s\n", sp->GDB);
sprintf(target_data.gdb_version, "%s", &sp->GDB[4]);
} else if (strncmp(buf, "LDFLAGS=", strlen("LDFLAGS=")) == 0) {
fprintf(fp2, "LDFLAGS=%s\n", ldflags ? ldflags : "");
} else
fprintf(fp2, "%s", buf);
}
makefile_create(&fp1, &fp2);
show_configuration();
make_build_data(&target[strlen("TARGET=")]);
}
void
release_configure(char *gdb_version, struct supported_gdb_version *sp)
{
FILE *fp1, *fp2;
int found;
char buf[512];
char gdb_files[MAXSTRLEN];
get_current_configuration(sp);
sprintf(buf, "%s/gdb", gdb_version);
if (!file_exists(buf)) {
fprintf(stderr, "make release: no such directory: %s\n", buf);
exit(1);
}
sprintf(gdb_files, "GDB_%s_FILES",
&gdb_version[strlen("gdb-")]);
makefile_setup(&fp1, &fp2);
found = 0;
while (fgets(buf, 512, fp1)) {
if (strncmp(buf, gdb_files, strlen(gdb_files)) == 0)
found++;
if (strncmp(buf, "GDB_FILES=", strlen("GDB_FILES=")) == 0)
fprintf(fp2, "GDB_FILES=${%s}\n", gdb_files);
else if (strncmp(buf, "VERSION=", strlen("VERSION=")) == 0)
fprintf(fp2, "VERSION=%s\n",
target_data.release);
else if (strncmp(buf, "GDB_PATCH_FILES=", strlen("GDB_PATCH_FILES=")) == 0)
fprintf(fp2, "%s\n", sp->GDB_PATCH_FILES);
else if (strncmp(buf, "GPL_FILES=", strlen("GPL_FILES=")) == 0)
fprintf(fp2, "GPL_FILES=%s\n", strcmp(sp->GPL, "GPLv2") == 0 ?
"COPYING" : "COPYING3");
else
fprintf(fp2, "%s", buf);
}
if (!found) {
fprintf(stderr, "make release: cannot find %s\n", gdb_files);
exit(1);
}
makefile_create(&fp1, &fp2);
}
/*
* Create an .rh_rpm_package file if the passed-in variable is set.
*/
void
make_rh_rpm_package(char *package, int release)
{
char *p, *cur;
FILE *fp;
char buf[256];
if ((strcmp(package, "remove") == 0)) {
if (file_exists(".rh_rpm_package")) {
if (unlink(".rh_rpm_package")) {
perror("unlink");
fprintf(stderr,
"cannot remove .rh_rpm_package\n");
exit(1);
}
}
return;
}
if (!(p = strstr(package, "=")))
return;
if (!strlen(++p))
return;
if (release) {
if (!(fp = popen("./crash -v", "r"))) {
fprintf(stderr, "cannot execute \"crash -v\"\n");
exit(1);
}
cur = NULL;
while (fgets(buf, 256, fp)) {
if (strncmp(buf, "crash ", 6) == 0) {
cur = &buf[6];
break;
}
}
pclose(fp);
if (!cur) {
fprintf(stderr, "cannot get version from \"crash -v\"\n");
exit(1);
}
strip_linefeeds(cur);
if (strcmp(cur, p) != 0) {
fprintf(stderr, "./crash version: %s\n", cur);
fprintf(stderr, "release version: %s\n", p);
exit(1);
}
}
if ((fp = fopen(".rh_rpm_package", "w")) == NULL) {
perror("fopen");
fprintf(stderr, "cannot open .rh_rpm_package\n");
exit(1);
}
fprintf(fp, "%s\n", strip_linefeeds(p));
fclose(fp);
}
void
gdb_configure(struct supported_gdb_version *sp)
{
FILE *fp1, *fp2;
char buf[512];
get_current_configuration(sp);
makefile_setup(&fp1, &fp2);
while (fgets(buf, 512, fp1)) {
if (strncmp(buf, "GDB=", strlen("GDB=")) == 0)
fprintf(fp2, "%s\n", sp->GDB);
else
fprintf(fp2, "%s", buf);
}
makefile_create(&fp1, &fp2);
}
void
unconfigure(void)
{
FILE *fp1, *fp2;
char buf[512];
makefile_setup(&fp1, &fp2);
while (fgets(buf, 512, fp1)) {
if (strncmp(buf, "TARGET=", strlen("TARGET=")) == 0)
fprintf(fp2, "TARGET=\n");
else if (strncmp(buf, "TARGET_CFLAGS=",
strlen("TARGET_CFLAGS=")) == 0)
fprintf(fp2, "TARGET_CFLAGS=\n");
else if (strncmp(buf, "GDB_CONF_FLAGS=",
strlen("GDB_CONF_FLAGS=")) == 0)
fprintf(fp2, "GDB_CONF_FLAGS=\n");
else if (strncmp(buf, "GDB_FILES=",strlen("GDB_FILES=")) == 0)
fprintf(fp2, "GDB_FILES=\n");
else if (strncmp(buf, "GDB_OFILES=",strlen("GDB_OFILES=")) == 0)
fprintf(fp2, "GDB_OFILES=\n");
else if (strncmp(buf, "GDB_PATCH_FILES=",strlen("GDB_PATCH_FILES=")) == 0)
fprintf(fp2, "GDB_PATCH_FILES=\n");
else if (strncmp(buf, "GDB_FLAGS=",strlen("GDB_FLAGS=")) == 0)
fprintf(fp2, "GDB_FLAGS=\n");
else if (strncmp(buf, "GDB=", strlen("GDB=")) == 0)
fprintf(fp2, "GDB=\n");
else if (strncmp(buf, "VERSION=", strlen("VERSION=")) == 0)
fprintf(fp2, "VERSION=\n");
else if (strncmp(buf, "GPL_FILES=", strlen("GPL_FILES=")) == 0)
fprintf(fp2, "GPL_FILES=\n");
else if (strncmp(buf, "LDFLAGS=", strlen("LDFLAGS=")) == 0)
fprintf(fp2, "LDFLAGS=\n");
else if (strncmp(buf, "WARNING_ERROR=",
strlen("WARNING_ERROR=")) == 0) {
shift_string_right(buf, 1);
buf[0] = '#';
fprintf(fp2, "%s", buf);
} else if (strncmp(buf, "WARNING_OPTIONS=",
strlen("WARNING_OPTIONS=")) == 0) {
shift_string_right(buf, 1);
buf[0] = '#';
fprintf(fp2, "%s", buf);
} else
fprintf(fp2, "%s", buf);
}
makefile_create(&fp1, &fp2);
}
void
set_warnings(int w)
{
FILE *fp1, *fp2;
char buf[512];
makefile_setup(&fp1, &fp2);
while (fgets(buf, 512, fp1)) {
if (strncmp(buf, "#WARNING_ERROR=",
strlen("#WARNING_ERROR=")) == 0) {
switch (w)
{
case 'W':
shift_string_left(buf, 1);
break;
case 'w':
case 'n':
break;
}
}
if (strncmp(buf, "WARNING_ERROR=",
strlen("WARNING_ERROR=")) == 0) {
switch (w)
{
case 'n':
case 'w':
shift_string_right(buf, 1);
buf[0] = '#';
break;
case 'W':
break;
}
}
if (strncmp(buf, "#WARNING_OPTIONS=",
strlen("#WARNING_OPTIONS=")) == 0) {
switch (w)
{
case 'W':
case 'w':
shift_string_left(buf, 1);
break;
case 'n':
break;
}
}
if (strncmp(buf, "WARNING_OPTIONS=",
strlen("WARNING_OPTIONS=")) == 0) {
switch (w)
{
case 'w':
case 'W':
break;
case 'n':
shift_string_right(buf, 1);
buf[0] = '#';
break;
}
}
fprintf(fp2, "%s", buf);
}
makefile_create(&fp1, &fp2);
}
void
makefile_setup(FILE **fp1, FILE **fp2)
{
if (stat("Makefile", &target_data.statbuf) == -1) {
perror("Makefile");
exit(1);
}
if ((*fp1 = fopen("Makefile", "r")) == NULL) {
perror("fopen");
fprintf(stderr, "cannot open existing Makefile\n");
exit(1);
}
unlink("Makefile.new");
if ((*fp2 = fopen("Makefile.new", "w+")) == NULL) {
perror("fopen");
fprintf(stderr, "cannot create new Makefile\n");
exit(1);
}
}
void
makefile_create(FILE **fp1, FILE **fp2)
{
fclose(*fp1);
fclose(*fp2);
if (system("mv Makefile.new Makefile") != 0) {
fprintf(stderr, "Makefile: cannot create new Makefile\n");
fprintf(stderr, "please copy Makefile.new to Makefile\n");
exit(1);
}
if (chown("Makefile", target_data.statbuf.st_uid,
target_data.statbuf.st_gid) == -1) {
fprintf(stderr,
"Makefile: cannot restore original owner/group\n");
}
}
#define LASTCHAR(s) (s[strlen(s)-1])
char *
strip_linefeeds(char *line)
{
char *p;
if (line == NULL || strlen(line) == 0)
return(line);
p = &LASTCHAR(line);
while (*p == '\n')
*p = '\0';
return(line);
}
/*
* Turn a string into upper-case.
*/
char *
upper_case(char *s, char *buf)
{
char *p1, *p2;
p1 = s;
p2 = buf;
while (*p1) {
*p2 = toupper(*p1);
p1++, p2++;
}
*p2 = '\0';
return(buf);
}
/*
* Turn a string into lower-case.
*/
char *
lower_case(char *s, char *buf)
{
char *p1, *p2;
p1 = s;
p2 = buf;
while (*p1) {
*p2 = tolower(*p1);
p1++, p2++;
}
*p2 = '\0';
return(buf);
}
char *
shift_string_left(char *s, int cnt)
{
int origlen;
if (!cnt)
return(s);
origlen = strlen(s);
memmove(s, s+cnt, (origlen-cnt));
*(s+(origlen-cnt)) = '\0';
return(s);
}
char *
shift_string_right(char *s, int cnt)
{
int i;
int origlen;
if (!cnt)
return(s);
origlen = strlen(s);
memmove(s+cnt, s, origlen);
*(s+(origlen+cnt)) = '\0';
for (i = 0; i < cnt; i++)
s[i] = ' ';
return(s);
}
char *
strip_beginning_whitespace(char *line)
{
char buf[MAXSTRLEN];
char *p;
if (line == NULL || strlen(line) == 0)
return(line);
strcpy(buf, line);
p = &buf[0];
while (*p == ' ' || *p == '\t')
p++;
strcpy(line, p);
return(line);
}
char *
strip_ending_whitespace(char *line)
{
char *p;
if (line == NULL || strlen(line) == 0)
return(line);
p = &line[strlen(line)-1];
while (*p == ' ' || *p == '\t') {
*p = '\0';
if (p == line)
break;
p--;
}
return(line);
}
int
file_exists(char *file)
{
struct stat sbuf;
if (stat(file, &sbuf) == 0)
return TRUE;
return FALSE;
}
int
count_chars(char *s, char c)
{
char *p;
int count;
if (!s)
return 0;
count = 0;
for (p = s; *p; p++) {
if (*p == c)
count++;
}
return count;
}
void
make_build_data(char *target)
{
char *p;
char hostname[MAXSTRLEN];
char progname[MAXSTRLEN];
char inbuf1[MAXSTRLEN];
char inbuf2[MAXSTRLEN];
char inbuf3[MAXSTRLEN];
FILE *fp1, *fp2, *fp3, *fp4;
unlink("build_data.c");
fp1 = popen("date", "r");
fp2 = popen("id", "r");
fp3 = popen("gcc --version", "r");
if ((fp4 = fopen("build_data.c", "w")) == NULL) {
perror("build_data.c");
exit(1);
}
if (gethostname(hostname, MAXSTRLEN) != 0)
hostname[0] = '\0';
p = fgets(inbuf1, 79, fp1);
p = fgets(inbuf2, 79, fp2);
p = strstr(inbuf2, " ");
*p = '\0';
p = fgets(inbuf3, 79, fp3);
lower_case(target_data.program, progname);
fprintf(fp4, "char *build_command = \"%s\";\n", progname);
if (getenv("SOURCE_DATE_EPOCH"))
fprintf(fp4, "char *build_data = \"reproducible build\";\n");
else if (strlen(hostname))
fprintf(fp4, "char *build_data = \"%s by %s on %s\";\n",
strip_linefeeds(inbuf1), inbuf2, hostname);
else
fprintf(fp4, "char *build_data = \"%s by %s\";\n",
strip_linefeeds(inbuf1), inbuf2);
bzero(inbuf1, MAXSTRLEN);
sprintf(inbuf1, "%s", target_data.release);
fprintf(fp4, "char *build_target = \"%s\";\n", target);
fprintf(fp4, "char *build_version = \"%s\";\n", inbuf1);
fprintf(fp4, "char *compiler_version = \"%s\";\n",
strip_linefeeds(inbuf3));
pclose(fp1);
pclose(fp2);
pclose(fp3);
fclose(fp4);
}
void
make_spec_file(struct supported_gdb_version *sp)
{
char *Version, *Release;
char buf[512];
get_current_configuration(sp);
Release = strstr(target_data.release, "-");
if (!Release) {
Version = target_data.release;
Release = "0";
} else {
fprintf(stderr,
"crash.spec: obsolete src.rpm build manner -- no dashes allowed: %s\n",
target_data.release);
return;
}
printf("#\n");
printf("# crash core analysis suite\n");
printf("#\n");
printf("Summary: crash utility for live systems; netdump, diskdump, kdump, LKCD or mcore dumpfiles\n");
printf("Name: %s\n", lower_case(target_data.program, buf));
printf("Version: %s\n", Version);
printf("Release: %s\n", Release);
printf("License: %s\n", sp->GPL);
printf("Group: Development/Debuggers\n");
printf("Source: %%{name}-%%{version}.tar.gz\n");
printf("URL: https://github.com/crash-utility\n");
printf("Distribution: Linux 2.2 or greater\n");
printf("Vendor: Red Hat, Inc.\n");
printf("Packager: Dave Anderson <anderson@redhat.com>\n");
printf("ExclusiveOS: Linux\n");
printf("ExclusiveArch: %%{ix86} alpha ia64 ppc ppc64 ppc64pseries ppc64iseries x86_64 s390 s390x arm aarch64 ppc64le mips mipsel mips64el sparc64 riscv64 loongarch64\n");
printf("Buildroot: %%{_tmppath}/%%{name}-root\n");
printf("BuildRequires: ncurses-devel zlib-devel bison\n");
printf("Requires: binutils\n");
printf("# Patch0: crash-3.3-20.installfix.patch (patch example)\n");
printf("\n");
printf("%%description\n");
printf("The core analysis suite is a self-contained tool that can be used to\n");
printf("investigate either live systems, kernel core dumps created from the\n");
printf("netdump, diskdump and kdump facilities from Red Hat Linux, the mcore kernel patch\n");
printf("offered by Mission Critical Linux, or the LKCD kernel patch.\n");
printf("\n");
printf("%%package devel\n");
printf("Requires: %%{name} = %%{version}, zlib-devel\n");
printf("Summary: crash utility for live systems; netdump, diskdump, kdump, LKCD or mcore dumpfiles\n");
printf("Group: Development/Debuggers\n");
printf("\n");
printf("%%description devel\n");
printf("The core analysis suite is a self-contained tool that can be used to\n");
printf("investigate either live systems, kernel core dumps created from the\n");
printf("netdump, diskdump and kdump packages from Red Hat Linux, the mcore kernel patch\n");
printf("offered by Mission Critical Linux, or the LKCD kernel patch.\n");
printf("\n");
printf("%%package extensions\n");
printf("Summary: Additional commands for the crash dump analysis tool\n");
printf("Group: Development/Debuggers\n");
printf("\n");
printf("%%description extensions\n");
printf("The extensions package contains plugins that provide additional crash\n");
printf("commands. The extensions can be loaded in crash via the \"extend\" command.\n");
printf("\n");
printf("The following extensions are provided:\n");
printf("* eppic: Provides C-like language for writing dump analysis scripts\n");
printf("* dminfo: Device-mapper target analyzer\n");
printf("* snap: Takes a snapshot of live memory and creates a kdump dumpfile\n");
printf("* trace: Displays kernel tracing data and traced events that occurred prior to a panic.\n");
printf("\n");
printf("%%prep\n");
printf("%%setup -n %%{name}-%%{version}\n");
printf("# %%patch0 -p1 -b .install (patch example)\n");
printf("\n");
printf("%%build\n");
printf("make RPMPKG=\"%%{version}\"\n");
printf("# make RPMPKG=\"%%{version}-%%{release}\"\n");
printf("make extensions\n");
/* printf("make crashd\n"); */
printf("\n");
printf("%%install\n");
printf("rm -rf %%{buildroot}\n");
printf("mkdir -p %%{buildroot}/usr/bin\n");
printf("make DESTDIR=%%{buildroot} install\n");
printf("mkdir -p %%{buildroot}%%{_mandir}/man8\n");
printf("cp crash.8 %%{buildroot}%%{_mandir}/man8/crash.8\n");
printf("mkdir -p %%{buildroot}%%{_includedir}/crash\n");
printf("cp defs.h %%{buildroot}%%{_includedir}/crash\n");
printf("mkdir -p %%{buildroot}%%{_libdir}/crash/extensions\n");
printf("if [ -f extensions/eppic.so ]\n");
printf("then\n");
printf("cp extensions/eppic.so %%{buildroot}%%{_libdir}/crash/extensions\n");
printf("fi\n");
printf("cp extensions/dminfo.so %%{buildroot}%%{_libdir}/crash/extensions\n");
printf("cp extensions/snap.so %%{buildroot}%%{_libdir}/crash/extensions\n");
printf("cp extensions/trace.so %%{buildroot}%%{_libdir}/crash/extensions\n");
printf("\n");
printf("%%clean\n");
printf("rm -rf %%{buildroot}\n");
printf("\n");
printf("%%files\n");
printf("%%defattr(-,root,root)\n");
printf("/usr/bin/crash\n");
printf("%%{_mandir}/man8/crash.8*\n");
/* printf("/usr/bin/crashd\n"); */
printf("%%doc README\n");
printf("\n");
printf("%%files devel\n");
printf("%%defattr(-,root,root)\n");
printf("%%{_includedir}/*\n");
printf("\n");
printf("%%files extensions\n");
printf("%%defattr(-,root,root)\n");
printf("%%{_libdir}/crash/extensions/*\n");
}
/*
* Use the default gdb #defines unless there's a .gdb file.
*/
struct supported_gdb_version *
setup_gdb_defaults(void)
{
FILE *fp;
char inbuf[512];
char buf[512];
struct supported_gdb_version *sp;
/*
* Use the default, allowing for an override in .gdb
*/
if (!file_exists(".gdb"))
return store_gdb_defaults(NULL);
if ((fp = fopen(".gdb", "r")) == NULL) {
perror(".gdb");
return store_gdb_defaults(NULL);
}
while (fgets(inbuf, 512, fp)) {
strip_linefeeds(inbuf);
strip_beginning_whitespace(inbuf);
strcpy(buf, inbuf);
/*
* Simple override.
*/
if (strcmp(buf, "5.3") == 0) {
fclose(fp);
sp = &supported_gdb_versions[GDB_5_3];
fprintf(stderr, ".gdb configuration: %s\n\n", sp->GDB_VERSION_IN);
return store_gdb_defaults(sp);
}
if (strcmp(buf, "6.0") == 0) {
fclose(fp);
sp = &supported_gdb_versions[GDB_6_0];
fprintf(stderr, ".gdb configuration: %s\n\n", sp->GDB_VERSION_IN);
return store_gdb_defaults(sp);
}
if (strcmp(buf, "6.1") == 0) {
fclose(fp);
sp = &supported_gdb_versions[GDB_6_1];
fprintf(stderr, ".gdb configuration: %s\n", sp->GDB_VERSION_IN);
return store_gdb_defaults(sp);
}
if (strcmp(buf, "7.0") == 0) {
fclose(fp);
sp = &supported_gdb_versions[GDB_7_0];
fprintf(stderr, ".gdb configuration: %s\n", sp->GDB_VERSION_IN);
return store_gdb_defaults(sp);
}
if (strcmp(buf, "7.3.1") == 0) {
fclose(fp);
sp = &supported_gdb_versions[GDB_7_3_1];
fprintf(stderr, ".gdb configuration: %s\n", sp->GDB_VERSION_IN);
return store_gdb_defaults(sp);
}
if (strcmp(buf, "7.6") == 0) {
fclose(fp);
sp = &supported_gdb_versions[GDB_7_6];
fprintf(stderr, ".gdb configuration: %s\n", sp->GDB_VERSION_IN);
return store_gdb_defaults(sp);
}
if (strcmp(buf, "10.2") == 0) {
fclose(fp);
sp = &supported_gdb_versions[GDB_10_2];
fprintf(stderr, ".gdb configuration: %s\n", sp->GDB_VERSION_IN);
return store_gdb_defaults(sp);
}
}
fclose(fp);
fprintf(stderr, ".gdb: rejected -- using default gdb\n\n");
return store_gdb_defaults(NULL);
}
struct supported_gdb_version *
store_gdb_defaults(struct supported_gdb_version *sp)
{
if (!sp)
sp = &supported_gdb_versions[default_gdb];
else
fprintf(stderr, "WARNING: \"make clean\" may be required before rebuilding\n\n");
return sp;
}
void
set_initial_target(struct supported_gdb_version *sp)
{
FILE *fp;
char crash_target[512];
char buf[512];
target_data.initial_gdb_target = UNKNOWN;
sprintf(crash_target, "%s/crash.target",
&sp->GDB[strlen("GDB=")]);
if (!file_exists(crash_target)) {
if (target_data.target_as_param &&
file_exists(&sp->GDB[strlen("GDB=")])) {
fprintf(stderr,
"\nThe \"%s\" file does not exist.\n",
crash_target);
target_rebuild_instructions(sp, (char *)target_data.target_as_param);
exit(1);
}
return;
}
if ((fp = fopen(crash_target, "r")) == NULL) {
perror(crash_target);
return;
}
if (!fgets(buf, 512, fp)) {
perror(crash_target);
fclose(fp);
return;
}
fclose(fp);
if (strncmp(buf, "X86_64", strlen("X86_64")) == 0)
target_data.initial_gdb_target = X86_64;
else if (strncmp(buf, "X86", strlen("X86")) == 0)
target_data.initial_gdb_target = X86;
else if (strncmp(buf, "ALPHA", strlen("ALPHA")) == 0)
target_data.initial_gdb_target = ALPHA;
else if (strncmp(buf, "PPC64", strlen("PPC64")) == 0)
target_data.initial_gdb_target = PPC64;
else if (strncmp(buf, "PPC", strlen("PPC")) == 0)
target_data.initial_gdb_target = PPC;
else if (strncmp(buf, "IA64", strlen("IA64")) == 0)
target_data.initial_gdb_target = IA64;
else if (strncmp(buf, "S390X", strlen("S390X")) == 0)
target_data.initial_gdb_target = S390X;
else if (strncmp(buf, "S390", strlen("S390")) == 0)
target_data.initial_gdb_target = S390;
else if (strncmp(buf, "ARM64", strlen("ARM64")) == 0)
target_data.initial_gdb_target = ARM64;
else if (strncmp(buf, "ARM", strlen("ARM")) == 0)
target_data.initial_gdb_target = ARM;
else if (strncmp(buf, "MIPS64", strlen("MIPS64")) == 0)
target_data.initial_gdb_target = MIPS64;
else if (strncmp(buf, "MIPS", strlen("MIPS")) == 0)
target_data.initial_gdb_target = MIPS;
else if (strncmp(buf, "SPARC64", strlen("SPARC64")) == 0)
target_data.initial_gdb_target = SPARC64;
else if (strncmp(buf, "RISCV64", strlen("RISCV64")) == 0)
target_data.initial_gdb_target = RISCV64;
else if (strncmp(buf, "LOONGARCH64", strlen("LOONGARCH64")) == 0)
target_data.initial_gdb_target = LOONGARCH64;
}
char *
target_to_name(int target)
{
switch (target)
{
case X86: return("X86");
case ALPHA: return("ALPHA");
case PPC: return("PPC");
case IA64: return("IA64");
case S390: return("S390");
case S390X: return("S390X");
case PPC64: return("PPC64");
case X86_64: return("X86_64");
case ARM: return("ARM");
case ARM64: return("ARM64");
case MIPS: return("MIPS");
case MIPS64: return("MIPS64");
case SPARC64: return("SPARC64");
case RISCV64: return("RISCV64");
case LOONGARCH64: return("LOONGARCH64");
}
return "UNKNOWN";
}
int
name_to_target(char *name)
{
if (strncmp(name, "X86_64", strlen("X86_64")) == 0)
return X86_64;
else if (strncmp(name, "x86_64", strlen("x86_64")) == 0)
return X86_64;
else if (strncmp(name, "X86", strlen("X86")) == 0)
return X86;
else if (strncmp(name, "x86", strlen("x86")) == 0)
return X86;
else if (strncmp(name, "ALPHA", strlen("ALPHA")) == 0)
return ALPHA;
else if (strncmp(name, "alpha", strlen("alpha")) == 0)
return ALPHA;
else if (strncmp(name, "PPC64", strlen("PPC64")) == 0)
return PPC64;
else if (strncmp(name, "ppc64", strlen("ppc64")) == 0)
return PPC64;
else if (strncmp(name, "ppc64le", strlen("ppc64le")) == 0)
return PPC64;
else if (strncmp(name, "PPC64LE", strlen("PPC64LE")) == 0)
return PPC64;
else if (strncmp(name, "PPC", strlen("PPC")) == 0)
return PPC;
else if (strncmp(name, "ppc", strlen("ppc")) == 0)
return PPC;
else if (strncmp(name, "IA64", strlen("IA64")) == 0)
return IA64;
else if (strncmp(name, "ia64", strlen("ia64")) == 0)
return IA64;
else if (strncmp(name, "S390X", strlen("S390X")) == 0)
return S390X;
else if (strncmp(name, "s390x", strlen("s390x")) == 0)
return S390X;
else if (strncmp(name, "S390", strlen("S390")) == 0)
return S390;
else if (strncmp(name, "s390", strlen("s390")) == 0)
return S390;
else if (strncmp(name, "ARM64", strlen("ARM64")) == 0)
return ARM64;
else if (strncmp(name, "arm64", strlen("arm64")) == 0)
return ARM64;
else if (strncmp(name, "aarch64", strlen("aarch64")) == 0)
return ARM64;
else if (strncmp(name, "ARM", strlen("ARM")) == 0)
return ARM;
else if (strncmp(name, "arm", strlen("arm")) == 0)
return ARM;
else if (strncmp(name, "mips", strlen("mips")) == 0)
return MIPS;
else if (strncmp(name, "MIPS", strlen("MIPS")) == 0)
return MIPS;
else if (strncmp(name, "mips64", strlen("mips64")) == 0)
return MIPS64;
else if (strncmp(name, "MIPS64", strlen("MIPS64")) == 0)
return MIPS64;
else if (strncmp(name, "sparc64", strlen("sparc64")) == 0)
return SPARC64;
else if (strncmp(name, "RISCV64", strlen("RISCV64")) == 0)
return RISCV64;
else if (strncmp(name, "riscv64", strlen("riscv64")) == 0)
return RISCV64;
else if (strncmp(name, "loongarch64", strlen("loongarch64")) == 0)
return LOONGARCH64;
else if (strncmp(name, "LOONGARCH64", strlen("LOONGARCH64")) == 0)
return LOONGARCH64;
return UNKNOWN;
}
char *
get_extra_flags(char *filename, char *initial)
{
FILE *fp;
char inbuf[512];
char buf[512];
if (!file_exists(filename))
return (initial ? initial : NULL);
if ((fp = fopen(filename, "r")) == NULL) {
perror(filename);
return (initial ? initial : NULL);
}
if (initial)
strcpy(buf, initial);
else
buf[0] = '\0';
while (fgets(inbuf, 512, fp)) {
strip_linefeeds(inbuf);
strip_beginning_whitespace(inbuf);
strip_ending_whitespace(inbuf);
if (inbuf[0] == '#')
continue;
if (strlen(inbuf)) {
if (strlen(buf))
strcat(buf, " ");
strcat(buf, inbuf);
}
}
fclose(fp);
if (strlen(buf))
return strdup(buf);
else
return NULL;
}
/*
* Add extra compression libraries. If not already there, create
* a CFLAGS.extra file and an LDFLAGS.extra file.
* For lzo:
* - enter -DLZO in the CFLAGS.extra file
* - enter -llzo2 in the LDFLAGS.extra file
*
* For snappy:
* - enter -DSNAPPY in the CFLAGS.extra file
* - enter -lsnappy in the LDFLAGS.extra file
*
* For zstd:
* - enter -DZSTD in the CFLAGS.extra file
* - enter -lzstd in the LDFLAGS.extra file
*
* For valgrind:
* - enter -DVALGRIND in the CFLAGS.extra file
*/
void
add_extra_lib(char *option)
{
int lzo, add_DLZO, add_llzo2;
int snappy, add_DSNAPPY, add_lsnappy;
int zstd, add_DZSTD, add_lzstd;
int valgrind, add_DVALGRIND;
char *cflags, *ldflags;
FILE *fp_cflags, *fp_ldflags;
char *mode;
char inbuf[512];
lzo = add_DLZO = add_llzo2 = 0;
snappy = add_DSNAPPY = add_lsnappy = 0;
zstd = add_DZSTD = add_lzstd = 0;
valgrind = add_DVALGRIND = 0;
ldflags = get_extra_flags("LDFLAGS.extra", NULL);
cflags = get_extra_flags("CFLAGS.extra", NULL);
if (strcmp(option, "lzo") == 0) {
lzo++;
if (!cflags || !strstr(cflags, "-DLZO"))
add_DLZO++;
if (!ldflags || !strstr(ldflags, "-llzo2"))
add_llzo2++;
}
if (strcmp(option, "snappy") == 0) {
snappy++;
if (!cflags || !strstr(cflags, "-DSNAPPY"))
add_DSNAPPY++;
if (!ldflags || !strstr(ldflags, "-lsnappy"))
add_lsnappy++;
}
if (strcmp(option, "zstd") == 0) {
zstd++;
if (!cflags || !strstr(cflags, "-DZSTD"))
add_DZSTD++;
if (!ldflags || !strstr(ldflags, "-lzstd"))
add_lzstd++;
}
if (strcmp(option, "valgrind") == 0) {
valgrind++;
if (!cflags || !strstr(cflags, "-DVALGRIND"))
add_DVALGRIND++;
}
if ((lzo || snappy || zstd) &&
file_exists("diskdump.o") && (unlink("diskdump.o") < 0)) {
perror("diskdump.o");
return;
}
if (valgrind &&
file_exists("tools.o") && (unlink("tools.o") < 0)) {
perror("tools.o");
return;
}
mode = file_exists("CFLAGS.extra") ? "r+" : "w+";
if ((fp_cflags = fopen("CFLAGS.extra", mode)) == NULL) {
perror("CFLAGS.extra");
return;
}
mode = file_exists("LDFLAGS.extra") ? "r+" : "w+";
if ((fp_ldflags = fopen("LDFLAGS.extra", mode)) == NULL) {
perror("LDFLAGS.extra");
fclose(fp_cflags);
return;
}
if (add_DLZO || add_DSNAPPY || add_DZSTD || add_DVALGRIND) {
while (fgets(inbuf, 512, fp_cflags))
;
if (add_DLZO)
fputs("-DLZO\n", fp_cflags);
if (add_DSNAPPY)
fputs("-DSNAPPY\n", fp_cflags);
if (add_DZSTD)
fputs("-DZSTD\n", fp_cflags);
if (add_DVALGRIND)
fputs("-DVALGRIND\n", fp_cflags);
}
if (add_llzo2 || add_lsnappy || add_lzstd) {
while (fgets(inbuf, 512, fp_ldflags))
;
if (add_llzo2)
fputs("-llzo2\n", fp_ldflags);
if (add_lsnappy)
fputs("-lsnappy\n", fp_ldflags);
if (add_lzstd)
fputs("-lzstd\n", fp_ldflags);
}
fclose(fp_cflags);
fclose(fp_ldflags);
}