]> granicus.if.org Git - strace/blob - ldt.c
bfin, csky, m68k, sh: fix build regression
[strace] / ldt.c
1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993-1996 Rick Sladkey <jrs@world.std.com>
5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6  * Copyright (c) 2002-2004 Roland McGrath <roland@redhat.com>
7  * Copyright (c) 2010 Andreas Schwab <schwab@linux-m68k.org>
8  * Copyright (c) 2014-2015 Dmitry V. Levin <ldv@altlinux.org>
9  * Copyright (c) 2014-2018 The strace developers.
10  * All rights reserved.
11  *
12  * SPDX-License-Identifier: LGPL-2.1-or-later
13  */
14
15 #include "defs.h"
16
17 #ifdef HAVE_STRUCT_USER_DESC
18
19 # include <asm/ldt.h>
20
21 # include "print_fields.h"
22 # include "xstring.h"
23
24 void
25 print_user_desc(struct tcb *const tcp, const kernel_ulong_t addr,
26                 enum user_desc_print_filter filter)
27 {
28         struct user_desc desc;
29         unsigned *entry_number = get_tcb_priv_data(tcp);
30
31         switch (filter) {
32         case USER_DESC_ENTERING:
33                 if (umove_or_printaddr(tcp, addr, &desc.entry_number))
34                         return;
35
36                 break;
37
38         case USER_DESC_EXITING:
39                 if (!addr || !verbose(tcp))
40                         return;
41                 if (syserror(tcp) || umove(tcp, addr, &desc)) {
42                         if (entry_number)
43                                 tprints(", ...}");
44
45                         return;
46                 }
47
48                 break;
49
50         case USER_DESC_BOTH:
51                 if (umove_or_printaddr(tcp, addr, &desc))
52                         return;
53
54                 break;
55         }
56
57         if (filter & USER_DESC_ENTERING) {
58                 PRINT_FIELD_ID("{", desc, entry_number);
59
60                 /*
61                  * If we don't print the whole structure now, let's save it for
62                  * later.
63                  */
64                 if (filter == USER_DESC_ENTERING) {
65                         entry_number = xmalloc(sizeof(*entry_number));
66
67                         *entry_number = desc.entry_number;
68                         set_tcb_priv_data(tcp, entry_number, free);
69                 }
70         }
71
72         if (filter & USER_DESC_EXITING) {
73                 /*
74                  * It should be the same in case of get_thread_area, but we can
75                  * never be sure...
76                  */
77                 if (filter == USER_DESC_EXITING) {
78                         if (entry_number) {
79                                 if (*entry_number != desc.entry_number) {
80                                         if ((int) desc.entry_number == -1)
81                                                 tprints(" => -1");
82                                         else
83                                                 tprintf(" => %u",
84                                                         desc.entry_number);
85                                 }
86                         } else {
87                                 /*
88                                  * This is really strange. If we are here, it
89                                  * means that we failed on entering but somehow
90                                  * succeeded on exiting.
91                                  */
92                                 PRINT_FIELD_ID(" => {", desc, entry_number);
93                         }
94                 }
95
96                 PRINT_FIELD_0X(", ", desc, base_addr);
97                 PRINT_FIELD_0X(", ", desc, limit);
98                 PRINT_FIELD_U_CAST(", ", desc, seg_32bit, unsigned int);
99                 PRINT_FIELD_U_CAST(", ", desc, contents, unsigned int);
100                 PRINT_FIELD_U_CAST(", ", desc, read_exec_only, unsigned int);
101                 PRINT_FIELD_U_CAST(", ", desc, limit_in_pages, unsigned int);
102                 PRINT_FIELD_U_CAST(", ", desc, seg_not_present, unsigned int);
103                 PRINT_FIELD_U_CAST(", ", desc, useable, unsigned int);
104
105 # ifdef HAVE_STRUCT_USER_DESC_LM
106                 /* lm is totally ignored for 32-bit processes */
107                 if (current_klongsize == 8)
108                         PRINT_FIELD_U_CAST(", ", desc, lm, unsigned int);
109 # endif /* HAVE_STRUCT_USER_DESC_LM */
110
111                 tprints("}");
112         }
113 }
114
115 SYS_FUNC(modify_ldt)
116 {
117         if (entering(tcp)) {
118                 tprintf("%d, ", (int) tcp->u_arg[0]);
119                 if (tcp->u_arg[2] != sizeof(struct user_desc))
120                         printaddr(tcp->u_arg[1]);
121                 else
122                         print_user_desc(tcp, tcp->u_arg[1], USER_DESC_BOTH);
123                 tprintf(", %" PRI_klu, tcp->u_arg[2]);
124
125                 return 0;
126         }
127
128         /*
129          * For some reason ("tht ABI for sys_modify_ldt() expects
130          * 'int'"), modify_ldt clips higher bits on x86_64.
131          */
132
133         if (syserror(tcp) || (kernel_ulong_t) tcp->u_rval < 0xfffff000)
134                 return 0;
135
136         tcp->u_error = -(unsigned int) tcp->u_rval;
137
138         return 0;
139 }
140
141 SYS_FUNC(set_thread_area)
142 {
143         if (entering(tcp)) {
144                 print_user_desc(tcp, tcp->u_arg[0], USER_DESC_BOTH);
145         } else {
146                 struct user_desc desc;
147
148                 if (!verbose(tcp) || syserror(tcp) ||
149                     umove(tcp, tcp->u_arg[0], &desc) < 0) {
150                         /* returned entry_number is not available */
151                 } else {
152                         static char outstr[32];
153
154                         xsprintf(outstr, "entry_number=%u", desc.entry_number);
155                         tcp->auxstr = outstr;
156                         return RVAL_STR;
157                 }
158         }
159         return 0;
160 }
161
162 SYS_FUNC(get_thread_area)
163 {
164         print_user_desc(tcp, tcp->u_arg[0],
165                         entering(tcp) ? USER_DESC_ENTERING : USER_DESC_EXITING);
166         return 0;
167 }
168
169 #endif /* HAVE_STRUCT_USER_DESC */
170
171 #if defined(M68K) || defined(MIPS)
172 SYS_FUNC(set_thread_area)
173 {
174         printaddr(tcp->u_arg[0]);
175
176         return RVAL_DECODED;
177
178 }
179 #endif
180
181 #if defined(M68K)
182 SYS_FUNC(get_thread_area)
183 {
184         return RVAL_DECODED | RVAL_HEX;
185 }
186 #endif