commit 8927806ad017c29f34a94a7f2d687c606132f736
Author: Joe Damato <ice799@gmail.com>
Date:   Mon Sep 7 01:38:11 2009 -0700

    Add new option '-g' '--no-plt' which disables setting breakpoints on PLTs. This
    is useful if the normal ltrace output is too overwhelming.

diff --git a/elf.c b/elf.c
index aeff211..795c062 100644
--- a/elf.c
+++ b/elf.c
@@ -468,95 +468,100 @@ read_elf(Process *proc) {
 	proc->e_machine = lte->ehdr.e_machine;
 	for (i = 0; i < library_num; ++i)
 		do_init_elf(&lte[i + 1], library[i]);
+
+	if (!options.no_plt) {
 #ifdef __mips__
-	// MIPS doesn't use the PLT and the GOT entries get changed
-	// on startup.
-	proc->need_to_reinitialize_breakpoints = 1;
-	for(i=lte->mips_gotsym; i<lte->dynsym_count;i++){
-		GElf_Sym sym;
-		const char *name;
-		GElf_Addr addr = arch_plt_sym_val(lte, i, 0);
-		if (gelf_getsym(lte->dynsym, i, &sym) == NULL){
-			error(EXIT_FAILURE, 0,
-					"Couldn't get relocation from \"%s\"",
-					proc->filename);
-		}
-		name=lte->dynstr+sym.st_name;
-		if(ELF64_ST_TYPE(sym.st_info) != STT_FUNC){
-			debug(2,"sym %s not a function",name);
-			continue;
+		// MIPS doesn't use the PLT and the GOT entries get changed
+		// on startup.
+		proc->need_to_reinitialize_breakpoints = 1;
+		for(i=lte->mips_gotsym; i<lte->dynsym_count;i++){
+			GElf_Sym sym;
+			const char *name;
+			GElf_Addr addr = arch_plt_sym_val(lte, i, 0);
+			if (gelf_getsym(lte->dynsym, i, &sym) == NULL){
+				error(EXIT_FAILURE, 0,
+						"Couldn't get relocation from \"%s\"",
+						proc->filename);
+			}
+			name=lte->dynstr+sym.st_name;
+			if(ELF64_ST_TYPE(sym.st_info) != STT_FUNC){
+				debug(2,"sym %s not a function",name);
+				continue;
+			}
+			add_library_symbol(addr, name, &library_symbols, 0,
+					ELF64_ST_BIND(sym.st_info) != 0);
+			if (!lib_tail)
+				lib_tail = &(library_symbols->next);
 		}
-		add_library_symbol(addr, name, &library_symbols, 0,
-				ELF64_ST_BIND(sym.st_info) != 0);
-		if (!lib_tail)
-			lib_tail = &(library_symbols->next);
-	}
 #else
-	for (i = 0; i < lte->relplt_count; ++i) {
-		GElf_Rel rel;
-		GElf_Rela rela;
-		GElf_Sym sym;
-		GElf_Addr addr;
-		void *ret;
-		const char *name;
+		for (i = 0; i < lte->relplt_count; ++i) {
+			GElf_Rel rel;
+			GElf_Rela rela;
+			GElf_Sym sym;
+			GElf_Addr addr;
+			void *ret;
+			const char *name;
+
+			if (lte->relplt->d_type == ELF_T_REL) {
+				ret = gelf_getrel(lte->relplt, i, &rel);
+				rela.r_offset = rel.r_offset;
+				rela.r_info = rel.r_info;
+				rela.r_addend = 0;
+			} else
+				ret = gelf_getrela(lte->relplt, i, &rela);
 
-		if (lte->relplt->d_type == ELF_T_REL) {
-			ret = gelf_getrel(lte->relplt, i, &rel);
-			rela.r_offset = rel.r_offset;
-			rela.r_info = rel.r_info;
-			rela.r_addend = 0;
-		} else
-			ret = gelf_getrela(lte->relplt, i, &rela);
-
-		if (ret == NULL
-		    || ELF64_R_SYM(rela.r_info) >= lte->dynsym_count
-		    || gelf_getsym(lte->dynsym, ELF64_R_SYM(rela.r_info),
-				   &sym) == NULL)
-			error(EXIT_FAILURE, 0,
-			      "Couldn't get relocation from \"%s\"",
-			      proc->filename);
+			if (ret == NULL
+					|| ELF64_R_SYM(rela.r_info) >= lte->dynsym_count
+					|| gelf_getsym(lte->dynsym, ELF64_R_SYM(rela.r_info),
+						&sym) == NULL)
+				error(EXIT_FAILURE, 0,
+						"Couldn't get relocation from \"%s\"",
+						proc->filename);
 
 #ifdef PLT_REINITALISATION_BP
-		if (!sym.st_value && PLTs_initialized_by_here)
-			proc->need_to_reinitialize_breakpoints = 1;
+			if (!sym.st_value && PLTs_initialized_by_here)
+				proc->need_to_reinitialize_breakpoints = 1;
 #endif
 
-		name = lte->dynstr + sym.st_name;
-		if (in_load_libraries(name, lte)) {
-			addr = arch_plt_sym_val(lte, i, &rela);
-			add_library_symbol(addr, name, &library_symbols,
-					   (PLTS_ARE_EXECUTABLE(lte)
-					   ?  LS_TOPLT_EXEC : LS_TOPLT_POINT),
-					   ELF64_ST_BIND(sym.st_info) == STB_WEAK);
-			if (!lib_tail)
-				lib_tail = &(library_symbols->next);
+			name = lte->dynstr + sym.st_name;
+			if (in_load_libraries(name, lte)) {
+				addr = arch_plt_sym_val(lte, i, &rela);
+				add_library_symbol(addr, name, &library_symbols,
+						(PLTS_ARE_EXECUTABLE(lte)
+						 ?	LS_TOPLT_EXEC : LS_TOPLT_POINT),
+						ELF64_ST_BIND(sym.st_info) == STB_WEAK);
+				if (!lib_tail)
+					lib_tail = &(library_symbols->next);
+			}
 		}
-	}
 #endif // !__mips__
 #ifdef PLT_REINITALISATION_BP
-	struct opt_x_t *main_cheat;
-
-	if (proc->need_to_reinitialize_breakpoints) {
-		/* Add "PLTs_initialized_by_here" to opt_x list, if not
-		   already there. */
-		main_cheat = (struct opt_x_t *)malloc(sizeof(struct opt_x_t));
-		if (main_cheat == NULL)
-			error(EXIT_FAILURE, 0, "Couldn't allocate memory");
-		main_cheat->next = opt_x;
-		main_cheat->found = 0;
-		main_cheat->name = PLTs_initialized_by_here;
-
-		for (xptr = opt_x; xptr; xptr = xptr->next)
-			if (strcmp(xptr->name, PLTs_initialized_by_here) == 0
-			    && main_cheat) {
-				free(main_cheat);
-				main_cheat = NULL;
-				break;
-			}
-		if (main_cheat)
-			opt_x = main_cheat;
-	}
+		struct opt_x_t *main_cheat;
+
+		if (proc->need_to_reinitialize_breakpoints) {
+			/* Add "PLTs_initialized_by_here" to opt_x list, if not
+				 already there. */
+			main_cheat = (struct opt_x_t *)malloc(sizeof(struct opt_x_t));
+			if (main_cheat == NULL)
+				error(EXIT_FAILURE, 0, "Couldn't allocate memory");
+			main_cheat->next = opt_x;
+			main_cheat->found = 0;
+			main_cheat->name = PLTs_initialized_by_here;
+
+			for (xptr = opt_x; xptr; xptr = xptr->next)
+				if (strcmp(xptr->name, PLTs_initialized_by_here) == 0
+						&& main_cheat) {
+					free(main_cheat);
+					main_cheat = NULL;
+					break;
+				}
+			if (main_cheat)
+				opt_x = main_cheat;
+		}
 #endif
+	} else {
+		lib_tail = &library_symbols;
+	}
 
 	for (i = 0; i < lte->symtab_count; ++i) {
 		GElf_Sym sym;
diff --git a/options.c b/options.c
index aef73b1..f2290b8 100644
--- a/options.c
+++ b/options.c
@@ -98,6 +98,7 @@ usage(void) {
 		"  -T                  show the time spent inside each call.\n"
 		"  -u USERNAME         run command with the userid, groupid of username.\n"
 		"  -V, --version       output version information and exit.\n"
+		"  -g, --no-plt        disable breakpoints on PLT entries.\n"
 		"  -x NAME             treat the global NAME like a library subroutine.\n"
 #ifdef PLT_REINITALISATION_BP
 		"  -X NAME             same as -x; and PLT's will be initialized by here.\n"
@@ -179,6 +180,7 @@ char **
 process_options(int argc, char **argv) {
 	progname = argv[0];
 	options.output = stderr;
+	options.no_plt = 0;
 
 	guess_cols();
 
@@ -198,9 +200,10 @@ process_options(int argc, char **argv) {
 			{"library", 1, 0, 'l'},
 			{"output", 1, 0, 'o'},
 			{"version", 0, 0, 'V'},
+			{"no-plt", 0, 0, 'g'},
 			{0, 0, 0, 0}
 		};
-		c = getopt_long(argc, argv, "+cfhiLrStTV"
+		c = getopt_long(argc, argv, "+cfhiLrStTVg"
 # ifdef USE_DEMANGLE
 				"C"
 # endif
@@ -351,6 +354,9 @@ process_options(int argc, char **argv) {
 					"This is free software; see the GNU General Public Licence\n"
 					"version 2 or later for copying conditions.  There is NO warranty.\n");
 			exit(0);
+		case 'g':
+			options.no_plt = 1;
+			break;
 		case 'X':
 #ifdef PLT_REINITALISATION_BP
 			PLTs_initialized_by_here = optarg;
diff --git a/options.h b/options.h
index db253c5..b74b495 100644
--- a/options.h
+++ b/options.h
@@ -14,6 +14,7 @@ struct options_t {
 	int arraylen; /* default maximum # of array elements printed */
 	int strlen;   /* default maximum # of bytes printed in strings */
 	int follow;   /* trace child processes */
+	int no_plt;   /* set bps on PLT entries */
 };
 extern struct options_t options;
 
