From 68004c84d6b852cfd4096cd211d2f8d3ff1d9f48 Mon Sep 17 00:00:00 2001 From: mmentovai Date: Fri, 28 Sep 2007 18:14:48 +0000 Subject: Solaris version of symbol dumper (#207). Patch by Alfred Peng. r=me http://groups.google.com/group/google-breakpad-dev/browse_thread/thread/e4cbdbf7ddaf7f51 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@218 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/client/linux/handler/Makefile | 2 +- src/client/solaris/handler/Makefile | 1 + src/common/linux/dump_symbols.cc | 2 +- src/common/linux/file_id.cc | 2 +- src/common/linux/md5.c | 246 --------- src/common/linux/md5.h | 31 -- src/common/md5.c | 246 +++++++++ src/common/md5.h | 31 ++ src/common/solaris/dump_symbols.cc | 587 +++++++++++++++++++++ src/common/solaris/dump_symbols.h | 49 ++ src/common/solaris/file_id.cc | 13 +- src/tools/linux/dump_syms/Makefile | 2 +- src/tools/solaris/dump_syms/Makefile | 64 +++ src/tools/solaris/dump_syms/dump_syms.cc | 54 ++ src/tools/solaris/dump_syms/run_regtest.sh | 51 ++ .../dump_syms/testdata/dump_syms_regtest.cc | 64 +++ .../solaris/dump_syms/testdata/dump_syms_regtest.o | Bin 0 -> 14204 bytes .../dump_syms/testdata/dump_syms_regtest.stabs | 129 +++++ .../dump_syms/testdata/dump_syms_regtest.sym | 33 ++ 19 files changed, 1319 insertions(+), 288 deletions(-) delete mode 100644 src/common/linux/md5.c delete mode 100644 src/common/linux/md5.h create mode 100644 src/common/md5.c create mode 100644 src/common/md5.h create mode 100644 src/common/solaris/dump_symbols.cc create mode 100644 src/common/solaris/dump_symbols.h create mode 100644 src/tools/solaris/dump_syms/Makefile create mode 100644 src/tools/solaris/dump_syms/dump_syms.cc create mode 100644 src/tools/solaris/dump_syms/run_regtest.sh create mode 100644 src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc create mode 100644 src/tools/solaris/dump_syms/testdata/dump_syms_regtest.o create mode 100644 src/tools/solaris/dump_syms/testdata/dump_syms_regtest.stabs create mode 100644 src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym (limited to 'src') diff --git a/src/client/linux/handler/Makefile b/src/client/linux/handler/Makefile index b28cc908..4609c75b 100644 --- a/src/client/linux/handler/Makefile +++ b/src/client/linux/handler/Makefile @@ -48,7 +48,7 @@ $(BIN_DIR)/minidump_test:$(MINIDUMP_TEST_OBJ) $(BIN_DIR)/exception_handler_test:$(EXCEPTION_TEST_OBJ) $(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ -md5.o:../../../common/linux/md5.c +md5.o:../../../common/md5.c $(CC) $(CXXFLAGS) -c $^ clean: diff --git a/src/client/solaris/handler/Makefile b/src/client/solaris/handler/Makefile index 318ac8e5..9b642865 100644 --- a/src/client/solaris/handler/Makefile +++ b/src/client/solaris/handler/Makefile @@ -40,6 +40,7 @@ BIN_DIR=. THREAD_SRC=solaris_lwp.cc SHARE_SRC=../../minidump_file_writer.cc\ + ../../../common/md5.c\ ../../../common/string_conversion.cc\ ../../../common/solaris/file_id.cc\ minidump_generator.cc diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc index 8c211579..bb3f81e9 100644 --- a/src/common/linux/dump_symbols.cc +++ b/src/common/linux/dump_symbols.cc @@ -494,7 +494,7 @@ bool WriteModuleInfo(int fd, ElfW(Half) arch, const std::string &obj_file) { size_t slash_pos = obj_file.find_last_of("/"); if (slash_pos != std::string::npos) filename = obj_file.substr(slash_pos + 1); - return WriteFormat(fd, "MODULE Linux %s %s %s\n", arch_name, + return WriteFormat(fd, "MODULE linux %s %s %s\n", arch_name, id_no_dash, filename.c_str()); } return false; diff --git a/src/common/linux/file_id.cc b/src/common/linux/file_id.cc index f8bb586e..d69d45a9 100644 --- a/src/common/linux/file_id.cc +++ b/src/common/linux/file_id.cc @@ -42,7 +42,7 @@ #include #include "common/linux/file_id.h" -#include "common/linux/md5.h" +#include "common/md5.h" namespace google_breakpad { diff --git a/src/common/linux/md5.c b/src/common/linux/md5.c deleted file mode 100644 index 60c1a782..00000000 --- a/src/common/linux/md5.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - */ - -#include - -#include "common/linux/md5.h" - -#ifndef WORDS_BIGENDIAN -#define byteReverse(buf, len) /* Nothing */ -#else -/* - * Note: this code is harmless on little-endian machines. - */ -static void byteReverse(unsigned char *buf, unsigned longs) -{ - u32 t; - do { - t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | - ((unsigned) buf[1] << 8 | buf[0]); - *(u32 *) buf = t; - buf += 4; - } while (--longs); -} -#endif - -static void MD5Transform(u32 buf[4], u32 const in[16]); - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void MD5Init(struct MD5Context *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) -{ - u32 t; - - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((u32) len << 3)) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; - - t = 64 - t; - if (len < t) { - memcpy(p, buf, len); - return; - } - memcpy(p, buf, t); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (u32 *) ctx->in); - buf += t; - len -= t; - } - /* Process data in 64-byte chunks */ - - while (len >= 64) { - memcpy(ctx->in, buf, 64); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (u32 *) ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memcpy(ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void MD5Final(unsigned char digest[16], struct MD5Context *ctx) -{ - unsigned count; - unsigned char *p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (u32 *) ctx->in); - - /* Now fill the next block with 56 bytes */ - memset(ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset(p, 0, count - 8); - } - byteReverse(ctx->in, 14); - - /* Append length in bits and transform */ - ((u32 *) ctx->in)[14] = ctx->bits[0]; - ((u32 *) ctx->in)[15] = ctx->bits[1]; - - MD5Transform(ctx->buf, (u32 *) ctx->in); - byteReverse((unsigned char *) ctx->buf, 4); - memcpy(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ -} - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -static void MD5Transform(u32 buf[4], u32 const in[16]) -{ - register u32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} diff --git a/src/common/linux/md5.h b/src/common/linux/md5.h deleted file mode 100644 index 03a13d6f..00000000 --- a/src/common/linux/md5.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2007 Google Inc. All Rights Reserved. -// Author: liuli@google.com (Liu Li) -#ifndef COMMON_LINUX_MD5_H__ -#define COMMON_LINUX_MD5_H__ - -#include - -typedef uint32_t u32; -typedef uint8_t u8; - -struct MD5Context { - u32 buf[4]; - u32 bits[2]; - u8 in[64]; -}; - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -void MD5Init(struct MD5Context *ctx); - -void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len); - -void MD5Final(unsigned char digest[16], struct MD5Context *ctx); - -#ifdef __cplusplus -} -#endif - -#endif // COMMON_LINUX_MD5_H__ diff --git a/src/common/md5.c b/src/common/md5.c new file mode 100644 index 00000000..7fc198af --- /dev/null +++ b/src/common/md5.c @@ -0,0 +1,246 @@ +/* + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +#include + +#include "common/md5.h" + +#ifndef WORDS_BIGENDIAN +#define byteReverse(buf, len) /* Nothing */ +#else +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse(unsigned char *buf, unsigned longs) +{ + u32 t; + do { + t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(u32 *) buf = t; + buf += 4; + } while (--longs); +} +#endif + +static void MD5Transform(u32 buf[4], u32 const in[16]); + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + u32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((u32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (u32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (u32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void MD5Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (u32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((u32 *) ctx->in)[14] = ctx->bits[0]; + ((u32 *) ctx->in)[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (u32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void MD5Transform(u32 buf[4], u32 const in[16]) +{ + register u32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} diff --git a/src/common/md5.h b/src/common/md5.h new file mode 100644 index 00000000..dbf4893c --- /dev/null +++ b/src/common/md5.h @@ -0,0 +1,31 @@ +// Copyright 2007 Google Inc. All Rights Reserved. +// Author: liuli@google.com (Liu Li) +#ifndef COMMON_MD5_H__ +#define COMMON_MD5_H__ + +#include + +typedef uint32_t u32; +typedef uint8_t u8; + +struct MD5Context { + u32 buf[4]; + u32 bits[2]; + u8 in[64]; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void MD5Init(struct MD5Context *ctx); + +void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len); + +void MD5Final(unsigned char digest[16], struct MD5Context *ctx); + +#ifdef __cplusplus +} +#endif + +#endif // COMMON_MD5_H__ diff --git a/src/common/solaris/dump_symbols.cc b/src/common/solaris/dump_symbols.cc new file mode 100644 index 00000000..b9fc74f6 --- /dev/null +++ b/src/common/solaris/dump_symbols.cc @@ -0,0 +1,587 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: Alfred Peng + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "common/solaris/dump_symbols.h" +#include "common/solaris/file_id.h" +#include "common/solaris/guid_creator.h" +#include "processor/scoped_ptr.h" + +// This namespace contains helper functions. +namespace { + +// Symbol table entry for stabs. Sun CC specific. +struct slist { + // String table index. + unsigned int n_strx; + // Stab type. + unsigned char n_type; + char n_other; + short n_desc; + unsigned long n_value; +}; + +// Infomation of a line. +struct LineInfo { + // Offset from start of the function. + // Load from stab symbol. + GElf_Off rva_to_func; + // Offset from base of the loading binary. + GElf_Off rva_to_base; + // Size of the line. + // The first line: equals to rva_to_func. + // The other lines: the difference of rva_to_func of the line and + // rva_to_func of the previous N_SLINE. + uint32_t size; + // Line number. + uint32_t line_num; +}; + +// Information of a function. +struct FuncInfo { + // Name of the function. + const char *name; + // Offset from the base of the loading address. + GElf_Off rva_to_base; + // Virtual address of the function. + // Load from stab symbol. + GElf_Addr addr; + // Size of the function. + // Equal to rva_to_func of the last function line. + uint32_t size; + // Total size of stack parameters. + uint32_t stack_param_size; + // Line information array. + std::vector line_info; +}; + +// Information of a source file. +struct SourceFileInfo { + // Name of the source file. + const char *name; + // Starting address of the source file. + GElf_Addr addr; + // Id of the source file. + int source_id; + // Functions information. + std::vector func_info; +}; + +// Information of a symbol table. +// This is the root of all types of symbol. +struct SymbolInfo { + std::vector source_file_info; +}; + +// Stab section name. +const char *kStabName = ".stab"; + +// Stab str section name. +const char *kStabStrName = ".stabstr"; + +// Default buffer lenght for demangle. +const int demangleLen = 2000; + +// Demangle using demangle library on Solaris. +std::string Demangle(const char *mangled) { + int status = 0; + char *demangled = (char *)malloc(demangleLen); + if (!demangled) { + fprintf(stderr, "no enough memory.\n"); + goto out; + } + + if ((status = cplus_demangle(mangled, demangled, demangleLen)) == + DEMANGLE_ESPACE) { + fprintf(stderr, "incorrect demangle.\n"); + goto out; + } + + std::string str(demangled); + free(demangled); + return str; + +out: + return std::string(mangled); +} + +// Find the prefered loading address of the binary. +GElf_Addr GetLoadingAddress(const GElf_Phdr *program_headers, int nheader) { + for (int i = 0; i < nheader; ++i) { + const GElf_Phdr &header = program_headers[i]; + // For executable, it is the PT_LOAD segment with offset to zero. + if (header.p_type == PT_LOAD && header.p_offset == 0) + return header.p_vaddr; + } + // For other types of ELF, return 0. + return 0; +} + +bool WriteFormat(int fd, const char *fmt, ...) { + va_list list; + char buffer[4096]; + ssize_t expected, written; + va_start(list, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, list); + expected = strlen(buffer); + written = write(fd, buffer, strlen(buffer)); + va_end(list); + return expected == written; +} + +bool IsValidElf(const GElf_Ehdr *elf_header) { + return memcmp(elf_header, ELFMAG, SELFMAG) == 0; +} + +static bool FindSectionByName(Elf *elf, const char *name, + int shstrndx, + GElf_Shdr *shdr) { + assert(name != NULL); + + if (strlen(name) == 0) + return false; + + Elf_Scn *scn = NULL; + + while ((scn = elf_nextscn(elf, scn)) != NULL) { + if (gelf_getshdr(scn, shdr) == (GElf_Shdr *)0) { + fprintf(stderr, "failed to read section header: %s\n", elf_errmsg(0)); + return false; + } + + const char *section_name = elf_strptr(elf, shstrndx, shdr->sh_name); + if (!section_name) { + fprintf(stderr, "Section name error: %s\n", elf_errmsg(-1)); + continue; + } + + if (strcmp(section_name, name) == 0) + return true; + } + + return false; +} + +// The parameter size is used for FPO-optimized code, and +// this is all tied up with the debugging data for Windows x86. +// Set it to 0 on Solaris. +int LoadStackParamSize(struct slist *list, + struct slist *list_end, + struct FuncInfo *func_info) { + struct slist *cur_list = list; + int step = 1; + while (cur_list < list_end && cur_list->n_type == N_PSYM) { + ++cur_list; + ++step; + } + + func_info->stack_param_size = 0; + return step; +} + +int LoadLineInfo(struct slist *list, + struct slist *list_end, + struct FuncInfo *func_info) { + struct slist *cur_list = list; + do { + // Skip non line information. + while (cur_list < list_end && cur_list->n_type != N_SLINE) { + // Only exit when got another function, or source file. + if (cur_list->n_type == N_FUN || cur_list->n_type == N_SO) + return cur_list - list; + ++cur_list; + } + struct LineInfo line; + while (cur_list < list_end && cur_list->n_type == N_SLINE) { + line.rva_to_func = cur_list->n_value; + // n_desc is a signed short + line.line_num = (unsigned short)cur_list->n_desc; + func_info->line_info.push_back(line); + ++cur_list; + } + if (cur_list == list_end && cur_list->n_type == N_ENDM) + break; + } while (list < list_end); + + return cur_list - list; +} + +int LoadFuncSymbols(struct slist *list, + struct slist *list_end, + const GElf_Shdr *stabstr_section, + GElf_Word base, + struct SourceFileInfo *source_file_info) { + struct slist *cur_list = list; + assert(cur_list->n_type == N_SO); + ++cur_list; + + source_file_info->func_info.clear(); + while (cur_list < list_end) { + // Go until the function symbol. + while (cur_list < list_end && cur_list->n_type != N_FUN) { + if (cur_list->n_type == N_SO) { + return cur_list - list; + } + ++cur_list; + continue; + } + while (cur_list->n_type == N_FUN) { + struct FuncInfo func_info; + memset(&func_info, 0, sizeof(func_info)); + func_info.name = + reinterpret_cast(cur_list->n_strx + + stabstr_section->sh_offset + base); + // The n_value field is always 0 from stab generated by Sun CC. + // TODO(Alfred): Find the correct value. + func_info.addr = cur_list->n_value; + ++cur_list; + if (cur_list->n_type != N_ESYM && cur_list->n_type != N_ISYM && + cur_list->n_type != N_FUN) { + // Stack parameter size. + cur_list += LoadStackParamSize(cur_list, list_end, &func_info); + // Line info. + cur_list += LoadLineInfo(cur_list, list_end, &func_info); + } + // Functions in this module should have address bigger than the module + // starting address. + // + // These two values are always 0 with Sun CC. + // TODO(Alfred): Get the correct value or remove the condition statement. + if (func_info.addr >= source_file_info->addr) { + source_file_info->func_info.push_back(func_info); + } + } + } + return cur_list - list; +} + +// Compute size and rva information based on symbols loaded from stab section. +bool ComputeSizeAndRVA(GElf_Addr loading_addr, struct SymbolInfo *symbols) { + std::vector *sorted_files = + &(symbols->source_file_info); + for (size_t i = 0; i < sorted_files->size(); ++i) { + struct SourceFileInfo &source_file = (*sorted_files)[i]; + std::vector *sorted_functions = &(source_file.func_info); + for (size_t j = 0; j < sorted_functions->size(); ++j) { + struct FuncInfo &func_info = (*sorted_functions)[j]; + assert(func_info.addr >= loading_addr); + func_info.rva_to_base = func_info.addr - loading_addr; + int line_count = func_info.line_info.size(); + func_info.size = + (line_count == 0) ? 0 : + func_info.line_info[line_count - 1].rva_to_func; + // Compute function and line size. + for (size_t k = 0; k < line_count; ++k) { + struct LineInfo &line_info = func_info.line_info[k]; + if (k == 0) { + line_info.size = line_info.rva_to_func; + } else { + line_info.size = + line_info.rva_to_func - func_info.line_info[k - 1].rva_to_func; + } + line_info.rva_to_base = line_info.rva_to_func + func_info.rva_to_base; + } // for each line. + } // for each function. + } // for each source file. + return true; +} + +bool LoadAllSymbols(const GElf_Shdr *stab_section, + const GElf_Shdr *stabstr_section, + GElf_Addr loading_addr, + GElf_Word base, + struct SymbolInfo *symbols) { + if (stab_section == NULL || stabstr_section == NULL) + return false; + + struct slist *lists = + reinterpret_cast(stab_section->sh_offset + base); + int nstab = stab_section->sh_size / sizeof(struct slist); + int source_id = 0; + // First pass, load all symbols from the object file. + for (int i = 0; i < nstab; ) { + int step = 1; + struct slist *cur_list = lists + i; + if (cur_list->n_type == N_SO) { + // FUNC
+ struct SourceFileInfo source_file_info; + source_file_info.name = + reinterpret_cast(cur_list->n_strx + + stabstr_section->sh_offset + base); + // The n_value field is always 0 from stab generated by Sun CC. + // TODO(Alfred): Find the correct value. + source_file_info.addr = cur_list->n_value; + if (strchr(source_file_info.name, '.')) + source_file_info.source_id = source_id++; + else + source_file_info.source_id = -1; + step = LoadFuncSymbols(cur_list, lists + nstab - 1, + stabstr_section, base, &source_file_info); + symbols->source_file_info.push_back(source_file_info); + } + i += step; + } + // Second pass, compute the size of functions and lines. + return ComputeSizeAndRVA(loading_addr, symbols); +} + +bool LoadSymbols(Elf *elf, GElf_Ehdr *elf_header, struct SymbolInfo *symbols, + void *obj_base) { + GElf_Word base = reinterpret_cast(obj_base); + GElf_Addr loading_addr = GetLoadingAddress( + reinterpret_cast(elf_header->e_phoff + base), + elf_header->e_phnum); + + const GElf_Shdr *sections = + reinterpret_cast(elf_header->e_shoff + base); + GElf_Shdr stab_section; + if (!FindSectionByName(elf, kStabName, elf_header->e_shstrndx, + &stab_section)) { + fprintf(stderr, "Stab section not found.\n"); + return false; + } + GElf_Shdr stabstr_section; + if (!FindSectionByName(elf, kStabStrName, elf_header->e_shstrndx, + &stabstr_section)) { + fprintf(stderr, "Stabstr section not found.\n"); + return false; + } + + // Load symbols. + return LoadAllSymbols(&stab_section, &stabstr_section, loading_addr, base, symbols); +} + +bool WriteModuleInfo(int fd, GElf_Half arch, const std::string &obj_file) { + const char *arch_name = NULL; + if (arch == EM_386) + arch_name = "x86"; + else if (arch == EM_X86_64) + arch_name = "x86_64"; + else + return false; + + unsigned char identifier[16]; + google_breakpad::FileID file_id(obj_file.c_str()); + if (file_id.ElfFileIdentifier(identifier)) { + char identifier_str[40]; + file_id.ConvertIdentifierToString(identifier, + identifier_str, sizeof(identifier_str)); + std::string filename = obj_file; + size_t slash_pos = obj_file.find_last_of("/"); + if (slash_pos != std::string::npos) + filename = obj_file.substr(slash_pos + 1); + return WriteFormat(fd, "MODULE solaris %s %s %s\n", arch_name, + identifier_str, filename.c_str()); + } + return false; +} + +bool WriteSourceFileInfo(int fd, const struct SymbolInfo &symbols) { + for (size_t i = 0; i < symbols.source_file_info.size(); ++i) { + if (symbols.source_file_info[i].source_id != -1) { + const char *name = symbols.source_file_info[i].name; + if (!WriteFormat(fd, "FILE %d %s\n", + symbols.source_file_info[i].source_id, name)) + return false; + } + } + return true; +} + +bool WriteOneFunction(int fd, int source_id, + const struct FuncInfo &func_info){ + // Discard the ending part of the name. + std::string func_name(func_info.name); + std::string::size_type last_colon = func_name.find_last_of(':'); + if (last_colon != std::string::npos) + func_name = func_name.substr(0, last_colon); + func_name = Demangle(func_name.c_str()); + + if (func_info.size < 0) + return true; + + // rva_to_base could be unsigned long(32 bit) or unsigned long long(64 bit). + if (WriteFormat(fd, "FUNC %llx %d %d %s\n", + (long long)func_info.rva_to_base, + func_info.size, + func_info.stack_param_size, + func_name.c_str())) { + for (size_t i = 0; i < func_info.line_info.size(); ++i) { + const struct LineInfo &line_info = func_info.line_info[i]; + if (!WriteFormat(fd, "%llx %d %d %d\n", + (long long)line_info.rva_to_base, + line_info.size, + line_info.line_num, + source_id)) + return false; + } + return true; + } + return false; +} + +bool WriteFunctionInfo(int fd, const struct SymbolInfo &symbols) { + for (size_t i = 0; i < symbols.source_file_info.size(); ++i) { + const struct SourceFileInfo &file_info = symbols.source_file_info[i]; + for (size_t j = 0; j < file_info.func_info.size(); ++j) { + const struct FuncInfo &func_info = file_info.func_info[j]; + if (!WriteOneFunction(fd, file_info.source_id, func_info)) + return false; + } + } + return true; +} + +bool DumpStabSymbols(int fd, const struct SymbolInfo &symbols) { + return WriteSourceFileInfo(fd, symbols) && + WriteFunctionInfo(fd, symbols); +} + +// +// FDWrapper +// +// Wrapper class to make sure opened file is closed. +// +class FDWrapper { + public: + explicit FDWrapper(int fd) : + fd_(fd) { + } + ~FDWrapper() { + if (fd_ != -1) + close(fd_); + } + int get() { + return fd_; + } + int release() { + int fd = fd_; + fd_ = -1; + return fd; + } + private: + int fd_; +}; + +// +// MmapWrapper +// +// Wrapper class to make sure mapped regions are unmapped. +// +class MmapWrapper { + public: + MmapWrapper(void *mapped_address, size_t mapped_size) : + base_(mapped_address), size_(mapped_size) { + } + ~MmapWrapper() { + if (base_ != NULL) { + assert(size_ > 0); + munmap((char *)base_, size_); + } + } + void release() { + base_ = NULL; + size_ = 0; + } + + private: + void *base_; + size_t size_; +}; + +} // namespace + +namespace google_breakpad { + +class AutoElfEnder { + public: + AutoElfEnder(Elf *elf) : elf_(elf) {} + ~AutoElfEnder() { if (elf_) elf_end(elf_); } + private: + Elf *elf_; +}; + + +bool DumpSymbols::WriteSymbolFile(const std::string &obj_file, int sym_fd) { + if (elf_version(EV_CURRENT) == EV_NONE) { + fprintf(stderr, "elf_version() failed: %s\n", elf_errmsg(0)); + return false; + } + + int obj_fd = open(obj_file.c_str(), O_RDONLY); + if (obj_fd < 0) + return false; + FDWrapper obj_fd_wrapper(obj_fd); + struct stat st; + if (fstat(obj_fd, &st) != 0 && st.st_size <= 0) + return false; + void *obj_base = mmap(NULL, st.st_size, + PROT_READ, MAP_PRIVATE, obj_fd, 0); + if (!obj_base) + return false; + MmapWrapper map_wrapper(obj_base, st.st_size); + GElf_Ehdr elf_header; + Elf *elf = elf_begin(obj_fd, ELF_C_READ, NULL); + AutoElfEnder elfEnder(elf); + + if (gelf_getehdr(elf, &elf_header) == (GElf_Ehdr *)NULL) { + fprintf(stderr, "failed to read elf header: %s\n", elf_errmsg(-1)); + return false; + } + + if (!IsValidElf(&elf_header)) { + fprintf(stderr, "header magic doesn't match\n"); + return false; + } + struct SymbolInfo symbols; + if (!LoadSymbols(elf, &elf_header, &symbols, obj_base)) + return false; + // Write to symbol file. + if (WriteModuleInfo(sym_fd, elf_header.e_machine, obj_file) && + DumpStabSymbols(sym_fd, symbols)) + return true; + + return false; +} + +} // namespace google_breakpad diff --git a/src/common/solaris/dump_symbols.h b/src/common/solaris/dump_symbols.h new file mode 100644 index 00000000..7f4baadc --- /dev/null +++ b/src/common/solaris/dump_symbols.h @@ -0,0 +1,49 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// dump_symbols.cc: Implements a Solaris stab debugging format dumper. +// +// Author: Alfred Peng + +#ifndef COMMON_SOLARIS_DUMP_SYMBOLS_H__ +#define COMMON_SOLARIS_DUMP_SYMBOLS_H__ + +#include + +namespace google_breakpad { + +class DumpSymbols { + public: + bool WriteSymbolFile(const std::string &obj_file, + int sym_fd); +}; + +} // namespace google_breakpad + +#endif // COMMON_SOLARIS_DUMP_SYMBOLS_H__ diff --git a/src/common/solaris/file_id.cc b/src/common/solaris/file_id.cc index 4bec3ed8..92e7f71f 100644 --- a/src/common/solaris/file_id.cc +++ b/src/common/solaris/file_id.cc @@ -36,8 +36,6 @@ #include #include #include -#include -#include #include #include #include @@ -47,6 +45,7 @@ #include #include +#include "common/md5.h" #include "common/solaris/file_id.h" #include "common/solaris/message_output.h" #include "google_breakpad/common/minidump_format.h" @@ -130,7 +129,7 @@ static bool FindElfTextSection(int fd, const void *elf_base, } FileID::FileID(const char *path) { - strncpy(path_, path, strlen(path)); + strcpy(path_, path); } class AutoCloser { @@ -160,10 +159,10 @@ bool FileID::ElfFileIdentifier(unsigned char identifier[16]) { int text_size = 0; if (FindElfTextSection(fd, base, &text_section, &text_size)) { - MD5_CTX md5; - MD5_Init(&md5); - MD5_Update(&md5, text_section, text_size); - MD5_Final(identifier, &md5); + MD5Context md5; + MD5Init(&md5); + MD5Update(&md5, (const unsigned char *)text_section, text_size); + MD5Final(identifier, &md5); success = true; } diff --git a/src/tools/linux/dump_syms/Makefile b/src/tools/linux/dump_syms/Makefile index 8e969586..7d74abad 100644 --- a/src/tools/linux/dump_syms/Makefile +++ b/src/tools/linux/dump_syms/Makefile @@ -23,7 +23,7 @@ guid_creator.o:../../../common/linux/guid_creator.cc file_id.o:../../../common/linux/file_id.cc $(CXX) $(CXXFLAGS) -c $^ -md5.o:../../../common/linux/md5.c +md5.o:../../../common/md5.c $(CC) $(CXXFLAGS) -c $^ clean: diff --git a/src/tools/solaris/dump_syms/Makefile b/src/tools/solaris/dump_syms/Makefile new file mode 100644 index 00000000..f0a4c11a --- /dev/null +++ b/src/tools/solaris/dump_syms/Makefile @@ -0,0 +1,64 @@ +# Copyright (c) 2007, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Author: Alfred Peng + +CXX=CC +CC=cc + +CXXFLAGS=-g -xs -xdebugformat=stabs -I../../.. -I../../../common/solaris -lelf -ldemangle -D_REENTRANT + +.PHONY:all clean + +BIN=dump_syms + +all:$(BIN) + +DUMP_OBJ=dump_symbols.o guid_creator.o dump_syms.o file_id.o md5.o + +dump_syms:$(DUMP_OBJ) + $(CXX) $(CXXFLAGS) -o $@ $^ + +dump_symbols.o:../../../common/solaris/dump_symbols.cc + $(CXX) $(CXXFLAGS) -c $^ + +guid_creator.o:../../../common/solaris/guid_creator.cc + $(CXX) $(CXXFLAGS) -c $^ + +file_id.o:../../../common/solaris/file_id.cc + $(CXX) $(CXXFLAGS) -c $^ + +md5.o:../../../common/md5.c + $(CC) $(CXXFLAGS) -c $^ + +test:all + ./run_regtest.sh + +clean: + rm -f $(BIN) $(DUMP_OBJ) diff --git a/src/tools/solaris/dump_syms/dump_syms.cc b/src/tools/solaris/dump_syms/dump_syms.cc new file mode 100644 index 00000000..54cea57e --- /dev/null +++ b/src/tools/solaris/dump_syms/dump_syms.cc @@ -0,0 +1,54 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: Alfred Peng + +#include +#include + +#include "common/solaris/dump_symbols.h" + +using namespace google_breakpad; + +int main(int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + const char *binary = argv[1]; + + DumpSymbols dumper; + if (!dumper.WriteSymbolFile(binary, fileno(stdout))) { + fprintf(stderr, "Failed to write symbol file.\n"); + return 1; + } + + return 0; +} diff --git a/src/tools/solaris/dump_syms/run_regtest.sh b/src/tools/solaris/dump_syms/run_regtest.sh new file mode 100644 index 00000000..ffb34330 --- /dev/null +++ b/src/tools/solaris/dump_syms/run_regtest.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +# Copyright (c) 2007, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +./dump_syms testdata/dump_syms_regtest.o > testdata/dump_syms_regtest.new +status=$? + +if [ $status -ne 0 ] ; then + echo "FAIL, dump_syms failed" + exit $status +fi + +diff -u testdata/dump_syms_regtest.new testdata/dump_syms_regtest.sym > \ + testdata/dump_syms_regtest.diff +status=$? + +if [ $status -eq 0 ] ; then + rm testdata/dump_syms_regtest.diff testdata/dump_syms_regtest.new + echo "PASS" +else + echo "FAIL, see testdata/dump_syms_regtest.[new|diff]" +fi + +exit $status diff --git a/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc b/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc new file mode 100644 index 00000000..e617a23b --- /dev/null +++ b/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc @@ -0,0 +1,64 @@ +// Copyright (c) 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ./dump_syms dump_syms_regtest.pdb > dump_syms_regtest.sym + +namespace google_breakpad { + +class C { + public: + C() : member_(1) {} + virtual ~C() {} + + void set_member(int value) { member_ = value; } + int member() const { return member_; } + + void f() { member_ = g(); } + virtual int g() { return 2; } + static char* h(const C &that) { return 0; } + + private: + int member_; +}; + +static int i() { + return 3; +} + +} // namespace google_breakpad + +int main(int argc, char **argv) { + google_breakpad::C object; + object.set_member(google_breakpad::i()); + object.f(); + int value = object.g(); + char *nothing = object.h(object); + + return 0; +} diff --git a/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.o b/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.o new file mode 100644 index 00000000..a1c61b2d Binary files /dev/null and b/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.o differ diff --git a/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.stabs b/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.stabs new file mode 100644 index 00000000..c5f93ef7 --- /dev/null +++ b/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.stabs @@ -0,0 +1,129 @@ + + +Debugging Stab table -- 104 entries + + 0: .stabs "dump_syms_regtest.cc",N_UNDF,0x0,0x67,0x71c + 1: .stabs "/export/home/alfred/cvs/breakpad/google-breakpad20070927/src/tools/solaris/dump_syms/testdata/",N_SO,0x0,0x0,0x0 + 2: .stabs "dump_syms_regtest.cc",N_SO,0x0,0x4,0x0 + 3: .stabs "",N_OBJ,0x0,0x0,0x0 + 4: .stabs "",N_OBJ,0x0,0x0,0x0 + 5: .stabs "V=9.0;DBG_GEN=5.0.8;dm;cd;backend;ptf;ptx;ptk;s;g;R=5.8<>;G=.XAB6Z2hOiL$Gl1b.;A=2",N_OPT,0x0,0x0,0x46fcb88e + 6: .stabs "dump_syms_regtest.cc",N_SOL,0x0,0x0,0x0 + 7: .stabs "char:t(0,1)=bsc1;0;8",N_ISYM,0x0,0x0,0x0 + 8: .stabs "short:t(0,2)=bs2;0;16",N_ISYM,0x0,0x0,0x0 + 9: .stabs "int:t(0,3)=bs4;0;32",N_ISYM,0x0,0x0,0x0 + 10: .stabs "long:t(0,4)=bs4;0;32",N_ISYM,0x0,0x0,0x0 + 11: .stabs "long long:t(0,5)=bs8;0;64",N_ISYM,0x0,0x0,0x0 + 12: .stabs "unsigned char:t(0,6)=buc1;0;8",N_ISYM,0x0,0x0,0x0 + 13: .stabs "unsigned short:t(0,7)=bu2;0;16",N_ISYM,0x0,0x0,0x0 + 14: .stabs "unsigned:t(0,8)=bu4;0;32",N_ISYM,0x0,0x0,0x0 + 15: .stabs "unsigned long:t(0,9)=bu4;0;32",N_ISYM,0x0,0x0,0x0 + 16: .stabs "unsigned long long:t(0,10)=bu8;0;64",N_ISYM,0x0,0x0,0x0 + 17: .stabs "signed char:t(0,11)=bsc1;0;8",N_ISYM,0x0,0x0,0x0 + 18: .stabs "wchar_t:t(0,12)=buc4;0;32",N_ISYM,0x0,0x0,0x0 + 19: .stabs "void:t(0,13)=bs0;0;0",N_ISYM,0x0,0x0,0x0 + 20: .stabs "float:t(0,14)=R1;4",N_ISYM,0x0,0x0,0x0 + 21: .stabs "double:t(0,15)=R2;8",N_ISYM,0x0,0x0,0x0 + 22: .stabs "long double:t(0,16)=R6;12",N_ISYM,0x0,0x0,0x0 + 23: .stabs "...:t(0,17)=buv4;0;32",N_ISYM,0x0,0x0,0x0 + 24: .stabs "bool:t(0,18)=bub1;0;8",N_ISYM,0x0,0x0,0x0 + 25: .stabs "__1nPgoogle_breakpad_:T(0,19)=Yn0google_breakpad;",N_ISYM,0x0,0x0,0x0 + 26: .stabs "nBC(0,19):U(0,20)",N_ESYM,0x0,0x0,0x0 + 27: .stabs "nBC(0,19):T(0,20)=Yc8C;;AcHmember_:(0,3),32,32;;Cc2t6M_v K2c2T6M_v CcKset_member6Mi_v CcGmember6kM_i CcBf6M_v K3cBg6M_i GcBh6Frk1_pc;;;2 0;;;;110;",N_ESYM,0x0,0x8,0x0 + 28: .stabs "main:F(0,3);(0,3);(0,21)=*(0,22)=*(0,1)",N_FUN,0x0,0x38,0x0 + 29: .stabs "main",N_MAIN,0x0,0x0,0x0 + 30: .stabs "argc:p(0,3)",N_PSYM,0x0,0x4,0x8 + 31: .stabs "argv:p(0,21)",N_PSYM,0x0,0x4,0xc + 32: .stabn N_LBRAC,0x0,0x1,0x12 + 33: .stabs "object:(0,20)",N_LSYM,0x0,0x8,0xfffffff4 + 34: .stabs "value:(0,3)",N_LSYM,0x0,0x4,0xfffffff0 + 35: .stabs "nothing:(0,22)",N_LSYM,0x0,0x4,0xffffffec + 36: .stabn N_SLINE,0x0,0x39,0x12 + 37: .stabs "object:2",N_CONSTRUCT,0x0,0xc,0x12 + 38: .stabn N_SLINE,0x2,0x3a,0x1e + 39: .stabn N_SLINE,0x0,0x3b,0x36 + 40: .stabn N_SLINE,0x0,0x3c,0x42 + 41: .stabn N_SLINE,0x0,0x3d,0x57 + 42: .stabn N_SLINE,0x0,0x3f,0x6c + 43: .stabs "2:0",N_DESTRUCT,0x0,0xc,0x73 + 44: .stabn N_SLINE,0xfffffffe,0x40,0x9c + 45: .stabn N_RBRAC,0x0,0x1,0x9c + 46: .stabs "__1cPgoogle_breakpadBi6F_i_:f(0,3)",N_FUN,0x0,0x32,0x0 + 47: .stabn N_LBRAC,0x0,0x1,0x6 + 48: .stabn N_SLINE,0x0,0x33,0x6 + 49: .stabn N_SLINE,0x0,0x34,0x10 + 50: .stabn N_RBRAC,0x0,0x1,0x10 + 51: .stabs "__1cPgoogle_breakpadBC2t6M_v_:F(0,13);(0,23)=*(0,20)",N_FUN,0x0,0x24,0x0 + 52: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8 + 53: .stabn N_LBRAC,0x0,0x1,0x3 + 54: .stabn N_SLINE,0x0,0x24,0x25 + 55: .stabn N_RBRAC,0x0,0x1,0x25 + 56: .stabs "__1cPgoogle_breakpadBC2T6M_v_:F(0,13);(0,23)",N_FUN,0x0,0x25,0x0 + 57: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8 + 58: .stabn N_LBRAC,0x0,0x1,0x3 + 59: .stabn N_SLINE,0x0,0x25,0x3 + 60: .stabn N_RBRAC,0x0,0x1,0x3 + 61: .stabs "__1cPgoogle_breakpadBCKset_member6Mi_v_:F(0,13);(0,23);(0,3)",N_FUN,0x0,0x27,0x0 + 62: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8 + 63: .stabs "value:p(0,3)",N_PSYM,0x0,0x4,0xc + 64: .stabn N_LBRAC,0x0,0x1,0x3 + 65: .stabn N_SLINE,0x0,0x27,0x3 + 66: .stabn N_SLINE,0x0,0x27,0xc + 67: .stabn N_RBRAC,0x0,0x1,0xc + 68: .stabs "__1cPgoogle_breakpadBCBf6M_v_:F(0,13);(0,23)",N_FUN,0x0,0x2a,0x0 + 69: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8 + 70: .stabn N_LBRAC,0x0,0x1,0x3 + 71: .stabn N_SLINE,0x0,0x2a,0x3 + 72: .stabn N_SLINE,0x0,0x2a,0x1d + 73: .stabn N_RBRAC,0x0,0x1,0x1d + 74: .stabs "__1cPgoogle_breakpadBCBg6M_i_:F(0,3);(0,23)",N_FUN,0x0,0x2b,0x0 + 75: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8 + 76: .stabn N_LBRAC,0x0,0x1,0x6 + 77: .stabn N_SLINE,0x0,0x2b,0x6 + 78: .stabn N_SLINE,0x0,0x2b,0x10 + 79: .stabn N_RBRAC,0x0,0x1,0x10 + 80: .stabs "__1cPgoogle_breakpadBCBh6Frk1_pc_:F(0,22);(0,24)=&(0,25)=k(0,20)",N_FUN,0x0,0x2c,0x0 + 81: .stabs "that:p(0,24)",N_PSYM,0x0,0x4,0x8 + 82: .stabn N_LBRAC,0x0,0x1,0x6 + 83: .stabn N_SLINE,0x0,0x2c,0x6 + 84: .stabn N_SLINE,0x0,0x2c,0x10 + 85: .stabn N_RBRAC,0x0,0x1,0x10 + 86: .stabs "__1cPgoogle_breakpadBC2T5B6M_v_:F(0,13);(0,23)",N_FUN,0x0,0x25,0x0 + 87: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8 + 88: .stabn N_LBRAC,0x0,0x1,0x3 + 89: .stabn N_SLINE,0x0,0x25,0xf + 90: .stabn N_RBRAC,0x0,0x1,0xf + 91: .stabs "__SLIP.DELETER__A:f(0,13);(0,23);(0,3)",N_FUN,0x0,0x25,0x0 + 92: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8 + 93: .stabs "delete:p(0,3)",N_PSYM,0x0,0x4,0xc + 94: .stabn N_LBRAC,0x0,0x1,0x3 + 95: .stabn N_LBRAC,0x0,0x2,0x3 + 96: .stabn N_RBRAC,0x0,0x2,0x28 + 97: .stabn N_RBRAC,0x0,0x1,0x28 + 98: .stabs "true:l(0,18);1",N_LSYM,0x0,0x4,0x0 + 99: .stabs "false:l(0,18);0",N_LSYM,0x0,0x4,0x0 + 100: .stabs "__1c2k6Fpv_v_:P(0,13);(0,26)=*(0,13)",N_FUN,0x0,0x0,0x0 + 101: .stabs "__1cPgoogle_breakpadBC2t5B6M_v_:F__1cPgoogle_breakpadBC2t6M_v_",N_ALIAS,0x0,0x0,0x0 + 102: .stabs "cbD__RTTI__1nPgoogle_breakpadBC_(0,19):YR(0,20)",N_LSYM,0x0,0x0,0x0 + 103: .stabn N_ENDM,0x0,0x0,0x0 + + +Index Stab table -- 17 entries + + 0: .stabs "dump_syms_regtest.cc",N_UNDF,0x0,0x10,0x3b1 + 1: .stabs "/export/home/alfred/cvs/breakpad/google-breakpad20070927/src/tools/solaris/dump_syms/testdata/",N_SO,0x0,0x0,0x0 + 2: .stabs "dump_syms_regtest.cc",N_SO,0x0,0x4,0x0 + 3: .stabs "/export/home/alfred/cvs/breakpad/google-breakpad20070927/src/tools/solaris/dump_syms/testdata",N_OBJ,0x0,0x0,0x0 + 4: .stabs "dump_syms_regtest.o",N_OBJ,0x0,0x0,0x0 + 5: .stabs "V=9.0;DBG_GEN=5.0.8;dm;cd;backend;ptf;ptx;ptk;s;g;R=5.8<>;G=.XAB6Z2hOiL$Gl1b.;A=2",N_OPT,0x0,0x0,0x46fcb88e + 6: .stabs "/export/home/alfred/cvs/breakpad/google-breakpad20070927/src/tools/solaris/dump_syms/testdata/; /ws/on10-tools-prc/SUNWspro/SS11/prod/bin/CC -g -xs -xdebugformat=stabs -I../../.. -I../../../common/solaris -D_REENTRANT -xs dump_syms_regtest.cc -Qoption ccfe -prefix -Qoption ccfe .XAB6Z2hOiL\$Gl1b.",N_CMDLINE,0x0,0x0,0x0 + 7: .stabs "__1nPgoogle_breakpadBC_:U",N_ESYM,0x0,0x0,0x0 + 8: .stabs "main",N_MAIN,0x0,0x0,0x0 + 9: .stabs "main",N_FUN,0x0,0x0,0x0 + 10: .stabs "__1cPgoogle_breakpadBC2t6M_v_",N_FUN,0x0,0x0,0x0 + 11: .stabs "__1cPgoogle_breakpadBC2T6M_v_",N_FUN,0x0,0x0,0x0 + 12: .stabs "__1cPgoogle_breakpadBCKset_member6Mi_v_",N_FUN,0x0,0x0,0x0 + 13: .stabs "__1cPgoogle_breakpadBCBf6M_v_",N_FUN,0x0,0x0,0x0 + 14: .stabs "__1cPgoogle_breakpadBCBg6M_i_",N_FUN,0x0,0x0,0x0 + 15: .stabs "__1cPgoogle_breakpadBCBh6Frk1_pc_",N_FUN,0x0,0x0,0x0 + 16: .stabs "__1cPgoogle_breakpadBC2T5B6M_v_",N_FUN,0x0,0x0,0x0 diff --git a/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym b/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym new file mode 100644 index 00000000..44d3c539 --- /dev/null +++ b/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym @@ -0,0 +1,33 @@ +MODULE solaris x86 3DC8191474338D8587339B5FB3E2C62A0 dump_syms_regtest.o +FILE 0 dump_syms_regtest.cc +FUNC 0 156 0 main +12 18 57 0 +1e 12 58 0 +36 24 59 0 +42 12 60 0 +57 21 61 0 +6c 21 63 0 +9c 48 64 0 +FUNC 0 16 0 int google_breakpad::i() +6 6 51 0 +10 10 52 0 +FUNC 0 37 0 google_breakpad::C::C() +25 37 36 0 +FUNC 0 3 0 google_breakpad::C::~C() +3 3 37 0 +FUNC 0 12 0 void google_breakpad::C::set_member(int) +3 3 39 0 +c 9 39 0 +FUNC 0 29 0 void google_breakpad::C::f() +3 3 42 0 +1d 26 42 0 +FUNC 0 16 0 int google_breakpad::C::g() +6 6 43 0 +10 10 43 0 +FUNC 0 16 0 char*google_breakpad::C::h(const google_breakpad::C&) +6 6 44 0 +10 10 44 0 +FUNC 0 15 0 google_breakpad::C::~C #Nvariant 1() +f 15 37 0 +FUNC 0 0 0 __SLIP.DELETER__A +FUNC 0 0 0 void operator delete(void*) -- cgit v1.2.1