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, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999-2023 The strace developers.
7 * All rights reserved.
8 *
9 * SPDX-License-Identifier: LGPL-2.1-or-later
10 */
11
12 #include "defs.h"
13 #include <sys/resource.h>
14
15 #include "xstring.h"
16
17 #include "xlat/resources.h"
18
19 static void
20 print_rlim64_t(uint64_t lim) {
21 const char *str = NULL;
22
23 if (lim == UINT64_MAX)
24 str = "RLIM64_INFINITY";
25 else if (lim > 1024 && lim % 1024 == 0) {
26 static char buf[sizeof(lim) * 3 + sizeof("*1024")];
27
28 xsprintf(buf, "%" PRIu64 "*1024", lim / 1024);
29 str = buf;
30 }
31
32 if (!str || xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV)
33 PRINT_VAL_U(lim);
34
35 if (!str || xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
36 return;
37
38 (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE
39 ? tprints_comment : tprints_string)(str);
40 }
41
42 static void
43 print_rlimit64(struct tcb *const tcp, const kernel_ulong_t addr)
44 {
45 struct rlimit_64 {
46 uint64_t rlim_cur;
47 uint64_t rlim_max;
48 } rlim;
49
50 if (!umove_or_printaddr(tcp, addr, &rlim)) {
51 tprint_struct_begin();
52 PRINT_FIELD_OBJ_VAL(rlim, rlim_cur, print_rlim64_t);
53 tprint_struct_next();
54 PRINT_FIELD_OBJ_VAL(rlim, rlim_max, print_rlim64_t);
55 tprint_struct_end();
56 }
57 }
58
59 #if !defined(current_wordsize) || current_wordsize == 4
60
61 static void
62 print_rlim32_t(uint32_t lim) {
63 const char *str = NULL;
64
65 if (lim == UINT32_MAX)
66 str = "RLIM_INFINITY";
67 else if (lim > 1024 && lim % 1024 == 0) {
68 static char buf[sizeof(lim) * 3 + sizeof("*1024")];
69
70 xsprintf(buf, "%" PRIu32 "*1024", lim / 1024);
71 str = buf;
72 }
73
74 if (!str || xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV)
75 PRINT_VAL_U(lim);
76
77 if (!str || xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
78 return;
79
80 (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE
81 ? tprints_comment : tprints_string)(str);
82 }
83
84 static void
85 print_rlimit32(struct tcb *const tcp, const kernel_ulong_t addr)
86 {
87 struct rlimit_32 {
88 uint32_t rlim_cur;
89 uint32_t rlim_max;
90 } rlim;
91
92 if (!umove_or_printaddr(tcp, addr, &rlim)) {
93 tprint_struct_begin();
94 PRINT_FIELD_OBJ_VAL(rlim, rlim_cur, print_rlim32_t);
95 tprint_struct_next();
96 PRINT_FIELD_OBJ_VAL(rlim, rlim_max, print_rlim32_t);
97 tprint_struct_end();
98 }
99 }
100
101 static void
102 decode_rlimit(struct tcb *const tcp, const kernel_ulong_t addr)
103 {
104 /*
105 * i386 is the only personality on X86_64 and X32
106 * with 32-bit rlim_t.
107 * When current_personality is X32, current_wordsize
108 * equals to 4 but rlim_t is 64-bit.
109 */
110 if (current_klongsize == 4)
111 print_rlimit32(tcp, addr);
112 else
113 print_rlimit64(tcp, addr);
114 }
115
116 #else /* defined(current_wordsize) && current_wordsize != 4 */
117
118 # define decode_rlimit print_rlimit64
119
120 #endif
121
122 SYS_FUNC(getrlimit)
123 {
124 if (entering(tcp)) {
125 /* resource */
126 printxval(resources, tcp->u_arg[0], "RLIMIT_???");
127 tprint_arg_next();
128 } else {
129 /* rlim */
130 decode_rlimit(tcp, tcp->u_arg[1]);
131 }
132 return 0;
133 }
134
135 SYS_FUNC(setrlimit)
136 {
137 /* resource */
138 printxval(resources, tcp->u_arg[0], "RLIMIT_???");
139 tprint_arg_next();
140
141 /* rlim */
142 decode_rlimit(tcp, tcp->u_arg[1]);
143
144 return RVAL_DECODED;
145 }
146
147 SYS_FUNC(prlimit64)
148 {
149 if (entering(tcp)) {
150 /* pid */
151 printpid(tcp, tcp->u_arg[0], PT_TGID);
152 tprint_arg_next();
153
154 /* resource */
155 printxval(resources, tcp->u_arg[1], "RLIMIT_???");
156 tprint_arg_next();
157
158 /* new_limit */
159 print_rlimit64(tcp, tcp->u_arg[2]);
160 tprint_arg_next();
161 } else {
162 /* old_limit */
163 print_rlimit64(tcp, tcp->u_arg[3]);
164 }
165 return 0;
166 }
167
168 #include "xlat/usagewho.h"
169
170 SYS_FUNC(getrusage)
171 {
172 if (entering(tcp)) {
173 /* who */
174 printxval(usagewho, tcp->u_arg[0], "RUSAGE_???");
175 tprint_arg_next();
176 } else {
177 /* usage */
178 printrusage(tcp, tcp->u_arg[1]);
179 }
180 return 0;
181 }
182
183 #ifdef ALPHA
184 SYS_FUNC(osf_getrusage)
185 {
186 if (entering(tcp)) {
187 /* who */
188 printxval(usagewho, tcp->u_arg[0], "RUSAGE_???");
189 tprint_arg_next();
190 } else {
191 /* usage */
192 printrusage32(tcp, tcp->u_arg[1]);
193 }
194 return 0;
195 }
196 #endif /* ALPHA */
197
198 #include "xlat/priorities.h"
199
200 static void
201 priority_print_who(struct tcb *tcp, int which, int who)
202 {
203 switch (which)
204 {
205 case PRIO_PROCESS:
206 printpid(tcp, who, PT_TGID);
207 break;
208 case PRIO_PGRP:
209 printpid(tcp, who, PT_PGID);
210 break;
211 default:
212 PRINT_VAL_D(who);
213 break;
214 }
215 }
216
217 SYS_FUNC(getpriority)
218 {
219 /* which */
220 printxval(priorities, tcp->u_arg[0], "PRIO_???");
221 tprint_arg_next();
222
223 /* who */
224 priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]);
225
226 return RVAL_DECODED;
227 }
228
229 SYS_FUNC(setpriority)
230 {
231 /* which */
232 printxval(priorities, tcp->u_arg[0], "PRIO_???");
233 tprint_arg_next();
234
235 /* who */
236 priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]);
237 tprint_arg_next();
238
239 /* prio */
240 PRINT_VAL_D((int) tcp->u_arg[2]);
241
242 return RVAL_DECODED;
243 }