MINOR: debug: let ha_dump_backtrace() dump a bit further for some callers

The dump state is now passed to the function so that the caller can adjust
the behavior. A new series of 4 values allow to stop *after* dumping main
instead of before it or any of the usual loops. This allows to also report
BUG_ON() that could happen very high in the call graph (e.g. startup, or
the scheduler itself) while still understanding what the call path was.
diff --git a/include/haproxy/debug.h b/include/haproxy/debug.h
index 5cec243..dd1668d 100644
--- a/include/haproxy/debug.h
+++ b/include/haproxy/debug.h
@@ -28,7 +28,7 @@
 extern unsigned int debug_commands_issued;
 void ha_task_dump(struct buffer *buf, const struct task *task, const char *pfx);
 void ha_thread_dump(struct buffer *buf, int thr, int calling_tid);
-void ha_dump_backtrace(struct buffer *buf, const char *prefix);
+void ha_dump_backtrace(struct buffer *buf, const char *prefix, int dump);
 void ha_backtrace_to_stderr();
 void ha_thread_dump_all_to_trash();
 void ha_panic();
diff --git a/src/debug.c b/src/debug.c
index 7d73fdc..fc2de92 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -55,16 +55,22 @@
 /* dumps a backtrace of the current thread that is appended to buffer <buf>.
  * Lines are prefixed with the string <prefix> which may be empty (used for
  * indenting). It is recommended to use this at a function's tail so that
- * the function does not appear in the call stack.
+ * the function does not appear in the call stack. The <dump> argument
+ * indicates what dump state to start from, and should usually be zero. It
+ * may be among the following values:
+ *   - 0: search usual callers before step 1, or directly jump to 2
+ *   - 1: skip usual callers before step 2
+ *   - 2: dump until polling loop, scheduler, or main() (excluded)
+ *   - 3: end
+ *   - 4-7: like 0 but stops *after* main.
  */
-void ha_dump_backtrace(struct buffer *buf, const char *prefix)
+void ha_dump_backtrace(struct buffer *buf, const char *prefix, int dump)
 {
 	struct buffer bak;
 	char pfx2[100];
 	void *callers[100];
 	int j, nptrs;
 	const void *addr;
-	int dump = 0;
 
 	nptrs = my_backtrace(callers, sizeof(callers)/sizeof(*callers));
 	if (!nptrs)
@@ -77,43 +83,50 @@
 	 * produce similar output to the following:
 	 */
 	chunk_appendf(buf, "%scall trace(%d):\n", prefix, nptrs);
-	for (j = 0; (j < nptrs || dump < 2); j++) {
-		if (j == nptrs && !dump) {
+	for (j = 0; (j < nptrs || (dump & 3) < 2); j++) {
+		if (j == nptrs && !(dump & 3)) {
 			/* we failed to spot the starting point of the
 			 * dump, let's start over dumping everything we
 			 * have.
 			 */
-			dump = 2;
+			dump += 2;
 			j = 0;
 		}
 		bak = *buf;
 		dump_addr_and_bytes(buf, pfx2, callers[j], 8);
 		addr = resolve_sym_name(buf, ": ", callers[j]);
-		if (dump == 0) {
+		if ((dump & 3) == 0) {
 			/* dump not started, will start *after*
 			 * ha_thread_dump_all_to_trash, ha_panic and ha_backtrace_to_stderr
 			 */
 			if (addr == ha_thread_dump_all_to_trash || addr == ha_panic ||
 			    addr == ha_backtrace_to_stderr)
-				dump = 1;
+				dump++;
 			*buf = bak;
 			continue;
 		}
 
-		if (dump == 1) {
+		if ((dump & 3) == 1) {
 			/* starting */
 			if (addr == ha_thread_dump_all_to_trash || addr == ha_panic ||
 			    addr == ha_backtrace_to_stderr) {
 				*buf = bak;
 				continue;
 			}
-			dump = 2;
+			dump++;
 		}
 
-		if (dump == 2) {
-			/* dumping */
-			if (addr == run_poll_loop || addr == main || addr == run_tasks_from_lists) {
-				dump = 3;
+		if ((dump & 3) == 2) {
+			/* still dumping */
+			if (dump == 6) {
+				/* we only stop *after* main and we must send the LF */
+				if (addr == main) {
+					j = nptrs;
+					dump++;
+				}
+			}
+			else if (addr == run_poll_loop || addr == main || addr == run_tasks_from_lists) {
+				dump++;
 				*buf = bak;
 				break;
 			}
@@ -129,7 +142,7 @@
 	char area[2048];
 	struct buffer b = b_make(area, sizeof(area), 0, 0);
 
-	ha_dump_backtrace(&b, "  ");
+	ha_dump_backtrace(&b, "  ", 4);
 	if (b.data)
 		write(2, b.area, b.data);
 }
@@ -189,7 +202,7 @@
 		 * so that the compiler uses tail merging and the current
 		 * function does not appear in the stack.
 		 */
-		ha_dump_backtrace(buf, "             ");
+		ha_dump_backtrace(buf, "             ", 0);
 	}
 }