aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--exec/exec.c53
-rw-r--r--exec/trace.c39
2 files changed, 78 insertions, 14 deletions
diff --git a/exec/exec.c b/exec/exec.c
index 662c8bf69d2..c7a73f221f5 100644
--- a/exec/exec.c
+++ b/exec/exec.c
@@ -26,6 +26,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
26#include <assert.h> 26#include <assert.h>
27#include <string.h> 27#include <string.h>
28#include <ctype.h> 28#include <ctype.h>
29#include <stdlib.h>
29 30
30#include <sys/ptrace.h> 31#include <sys/ptrace.h>
31#include <sys/param.h> 32#include <sys/param.h>
@@ -808,6 +809,35 @@ insert_args (struct exec_tracee *tracee, USER_REGS_STRUCT *regs,
808 809
809 810
810 811
812/* Format PID, an unsigned process identifier, in base 10. Place the
813 result in *IN, and return a pointer to the byte after the
814 result. REM should be NULL. */
815
816static char *
817format_pid (char *in, unsigned int pid)
818{
819 unsigned int digits[32], *fill;
820
821 fill = digits;
822
823 for (; pid != 0; pid = pid / 10)
824 *fill++ = pid % 10;
825
826 /* Insert 0 if the number would otherwise be empty. */
827
828 if (fill == digits)
829 *fill++ = 0;
830
831 while (fill != digits)
832 {
833 --fill;
834 *in++ = '0' + *fill;
835 }
836
837 *in = '\0';
838 return in;
839}
840
811/* Return a sequence of actions required to load the executable under 841/* Return a sequence of actions required to load the executable under
812 the file NAME for the given TRACEE. First, see if the file starts 842 the file NAME for the given TRACEE. First, see if the file starts
813 with #!; in that case, find the program to open and use that 843 with #!; in that case, find the program to open and use that
@@ -836,6 +866,29 @@ exec_0 (const char *name, struct exec_tracee *tracee,
836#if defined __mips__ && !defined MIPS_NABI 866#if defined __mips__ && !defined MIPS_NABI
837 int fpu_mode; 867 int fpu_mode;
838#endif /* defined __mips__ && !defined MIPS_NABI */ 868#endif /* defined __mips__ && !defined MIPS_NABI */
869 char buffer[PATH_MAX + 80], *rewrite;
870 size_t remaining;
871
872 /* If name is not absolute, then make it relative to TRACEE's
873 cwd. Use stpcpy, as sprintf is not reentrant. */
874
875 if (name[0] && name[0] != '/')
876 {
877 /* Clear `buffer'. */
878 memset (buffer, 0, sizeof buffer);
879
880 /* Copy over /proc, the PID, and /cwd/. */
881 rewrite = stpcpy (buffer, "/proc/");
882 rewrite = format_pid (rewrite, tracee->pid);
883 rewrite = stpcpy (rewrite, "/cwd/");
884
885 /* Make sure there is enough free space. */
886 remaining = buffer + sizeof buffer - rewrite - 1;
887 rewrite = stpncpy (rewrite, name, remaining);
888
889 /* Replace name with buffer. */
890 name = buffer;
891 }
839 892
840 fd = open (name, O_RDONLY); 893 fd = open (name, O_RDONLY);
841 if (fd < 0) 894 if (fd < 0)
diff --git a/exec/trace.c b/exec/trace.c
index df5deacd9bb..d9e8673ba71 100644
--- a/exec/trace.c
+++ b/exec/trace.c
@@ -457,10 +457,17 @@ handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs)
457 memcpy (&original, regs, sizeof *regs); 457 memcpy (&original, regs, sizeof *regs);
458 458
459 /* Figure out what the loader needs to do. */ 459 /* Figure out what the loader needs to do. */
460 again1:
460 area = exec_0 (buffer, tracee, &size, regs); 461 area = exec_0 (buffer, tracee, &size, regs);
461 462
462 if (!area) 463 if (!area)
463 return 1; 464 {
465 /* Handle SIGINTR errors caused by IO. */
466 if (errno == EINTR)
467 goto again1;
468
469 return 1;
470 }
464 471
465 /* Rewrite the first argument to point to the loader. */ 472 /* Rewrite the first argument to point to the loader. */
466 473
@@ -516,10 +523,7 @@ handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs)
516 goto again; 523 goto again;
517 524
518 if (rc < 0) 525 if (rc < 0)
519 { 526 return 1;
520 errno = EIO;
521 return 1;
522 }
523 527
524 if (!WIFSTOPPED (wstatus)) 528 if (!WIFSTOPPED (wstatus))
525 /* The process has been killed in response to a signal. 529 /* The process has been killed in response to a signal.
@@ -608,13 +612,14 @@ handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs)
608 612
609#endif /* STACK_GROWS_DOWNWARDS */ 613#endif /* STACK_GROWS_DOWNWARDS */
610 614
611 exec_failure:
612
613 /* Continue. */ 615 /* Continue. */
614 if (ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0)) 616 if (ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0))
615 return 3; 617 return 3;
616 618
617 return 0; 619 return 0;
620
621 exec_failure:
622 return 3;
618} 623}
619 624
620/* Process the system call at which TRACEE is stopped. If the system 625/* Process the system call at which TRACEE is stopped. If the system
@@ -625,10 +630,10 @@ static void
625process_system_call (struct exec_tracee *tracee) 630process_system_call (struct exec_tracee *tracee)
626{ 631{
627 USER_REGS_STRUCT regs; 632 USER_REGS_STRUCT regs;
628 int rc, wstatus; 633 int rc, wstatus, save_errno;
629 USER_WORD callno, sp; 634 USER_WORD callno, sp;
630#ifdef __aarch64__ 635#ifdef __aarch64__
631 USER_WORD old_w0, old_w1, old_w2; 636 USER_WORD old_w1, old_w2;
632#endif /* __aarch64__ */ 637#endif /* __aarch64__ */
633 638
634#ifdef __aarch64__ 639#ifdef __aarch64__
@@ -695,6 +700,9 @@ process_system_call (struct exec_tracee *tracee)
695 Make sure that the stack pointer is restored to its original 700 Make sure that the stack pointer is restored to its original
696 position upon exit, or bad things can happen. */ 701 position upon exit, or bad things can happen. */
697 702
703 /* First, save errno; system calls below will clobber it. */
704 save_errno = errno;
705
698#ifndef __aarch64__ 706#ifndef __aarch64__
699 regs.SYSCALL_NUM_REG = -1; 707 regs.SYSCALL_NUM_REG = -1;
700#else /* __aarch64__ */ 708#else /* __aarch64__ */
@@ -702,7 +710,6 @@ process_system_call (struct exec_tracee *tracee)
702 can't find any unused system call, so use fcntl instead, with 710 can't find any unused system call, so use fcntl instead, with
703 invalid arguments. */ 711 invalid arguments. */
704 regs.SYSCALL_NUM_REG = 72; 712 regs.SYSCALL_NUM_REG = 72;
705 old_w0 = regs.regs[0];
706 old_w1 = regs.regs[1]; 713 old_w1 = regs.regs[1];
707 old_w2 = regs.regs[2]; 714 old_w2 = regs.regs[2];
708 regs.regs[0] = -1; 715 regs.regs[0] = -1;
@@ -739,6 +746,11 @@ process_system_call (struct exec_tracee *tracee)
739 if (rc == -1 && errno == EINTR) 746 if (rc == -1 && errno == EINTR)
740 goto again1; 747 goto again1;
741 748
749 /* Return if waitpid fails. */
750
751 if (rc == -1)
752 return;
753
742 if (!WIFSTOPPED (wstatus)) 754 if (!WIFSTOPPED (wstatus))
743 /* The process has been killed in response to a signal. In this 755 /* The process has been killed in response to a signal. In this
744 case, simply unlink the tracee and return. */ 756 case, simply unlink the tracee and return. */
@@ -747,16 +759,15 @@ process_system_call (struct exec_tracee *tracee)
747 { 759 {
748#ifdef __mips__ 760#ifdef __mips__
749 /* MIPS systems place errno in v0 and set a3 to 1. */ 761 /* MIPS systems place errno in v0 and set a3 to 1. */
750 regs.gregs[2] = errno; 762 regs.gregs[2] = save_errno;
751 regs.gregs[7] = 1; 763 regs.gregs[7] = 1;
752#else /* !__mips__ */ 764#else /* !__mips__ */
753 regs.SYSCALL_RET_REG = -errno; 765 regs.SYSCALL_RET_REG = -save_errno;
754#endif /* __mips__ */ 766#endif /* __mips__ */
755 767
756 /* Report errno. */ 768 /* Report errno. */
757#ifdef __aarch64__ 769#ifdef __aarch64__
758 /* Restore x0, x1 and x2. */ 770 /* Restore x1 and x2. x0 is clobbered by errno. */
759 regs.regs[0] = old_w0;
760 regs.regs[1] = old_w1; 771 regs.regs[1] = old_w1;
761 regs.regs[2] = old_w2; 772 regs.regs[2] = old_w2;
762 aarch64_set_regs (tracee->pid, &regs, false); 773 aarch64_set_regs (tracee->pid, &regs, false);