1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* 26 * Copyright (c) 2013 by Delphix. All rights reserved. 27 * Copyright 2023 Oxide Computer Company 28 */ 29 30 #include <stdarg.h> 31 #include <string.h> 32 #include <errno.h> 33 #include "Pcontrol.h" 34 35 /* 36 * This file implements the process services declared in <proc_service.h>. 37 * This enables libproc to be used in conjunction with libc_db and 38 * librtld_db. As most of these facilities are already provided by 39 * (more elegant) interfaces in <libproc.h>, we can just call those. 40 * 41 * NOTE: We explicitly do *not* implement the functions ps_kill() and 42 * ps_lrolltoaddr() in this library. The very existence of these functions 43 * causes libc_db to create an "agent thread" in the target process. 44 * The only way to turn off this behavior is to omit these functions. 45 */ 46 47 #pragma weak ps_pdread = ps_pread 48 #pragma weak ps_ptread = ps_pread 49 #pragma weak ps_pdwrite = ps_pwrite 50 #pragma weak ps_ptwrite = ps_pwrite 51 52 ps_err_e 53 ps_pdmodel(struct ps_prochandle *P, int *modelp) 54 { 55 *modelp = P->status.pr_dmodel; 56 return (PS_OK); 57 } 58 59 ps_err_e 60 ps_pread(struct ps_prochandle *P, psaddr_t addr, void *buf, size_t size) 61 { 62 if (P->ops.pop_pread(P, buf, size, addr, P->data) != size) 63 return (PS_BADADDR); 64 return (PS_OK); 65 } 66 67 ps_err_e 68 ps_pwrite(struct ps_prochandle *P, psaddr_t addr, const void *buf, size_t size) 69 { 70 if (P->ops.pop_pwrite(P, buf, size, addr, P->data) != size) 71 return (PS_BADADDR); 72 return (PS_OK); 73 } 74 75 /* 76 * libc_db calls matched pairs of ps_pstop()/ps_pcontinue() 77 * in the belief that the client may have left the process 78 * running while calling in to the libc_db interfaces. 79 * 80 * We interpret the meaning of these functions to be an inquiry 81 * as to whether the process is stopped, not an action to be 82 * performed to make it stopped. For similar reasons, we also 83 * return PS_OK for core files in order to allow libc_db to 84 * operate on these as well. 85 */ 86 ps_err_e 87 ps_pstop(struct ps_prochandle *P) 88 { 89 if (P->state != PS_STOP && P->state != PS_DEAD) 90 return (PS_ERR); 91 return (PS_OK); 92 } 93 94 ps_err_e 95 ps_pcontinue(struct ps_prochandle *P) 96 { 97 if (P->state != PS_STOP && P->state != PS_DEAD) 98 return (PS_ERR); 99 return (PS_OK); 100 } 101 102 /* 103 * ps_lstop() and ps_lcontinue() are not called by any code in libc_db 104 * or librtld_db. We make them behave like ps_pstop() and ps_pcontinue(). 105 */ 106 /* ARGSUSED1 */ 107 ps_err_e 108 ps_lstop(struct ps_prochandle *P, lwpid_t lwpid) 109 { 110 if (P->state != PS_STOP && P->state != PS_DEAD) 111 return (PS_ERR); 112 return (PS_OK); 113 } 114 115 /* ARGSUSED1 */ 116 ps_err_e 117 ps_lcontinue(struct ps_prochandle *P, lwpid_t lwpid) 118 { 119 if (P->state != PS_STOP && P->state != PS_DEAD) 120 return (PS_ERR); 121 return (PS_OK); 122 } 123 124 ps_err_e 125 ps_lgetregs(struct ps_prochandle *P, lwpid_t lwpid, prgregset_t regs) 126 { 127 if (P->state != PS_STOP && P->state != PS_DEAD) 128 return (PS_ERR); 129 130 if (Plwp_getregs(P, lwpid, regs) == 0) 131 return (PS_OK); 132 133 return (PS_BADLID); 134 } 135 136 ps_err_e 137 ps_lsetregs(struct ps_prochandle *P, lwpid_t lwpid, const prgregset_t regs) 138 { 139 if (P->state != PS_STOP) 140 return (PS_ERR); 141 142 if (Plwp_setregs(P, lwpid, regs) == 0) 143 return (PS_OK); 144 145 return (PS_BADLID); 146 } 147 148 ps_err_e 149 ps_lgetfpregs(struct ps_prochandle *P, lwpid_t lwpid, prfpregset_t *regs) 150 { 151 if (P->state != PS_STOP && P->state != PS_DEAD) 152 return (PS_ERR); 153 154 if (Plwp_getfpregs(P, lwpid, regs) == 0) 155 return (PS_OK); 156 157 return (PS_BADLID); 158 } 159 160 ps_err_e 161 ps_lsetfpregs(struct ps_prochandle *P, lwpid_t lwpid, const prfpregset_t *regs) 162 { 163 if (P->state != PS_STOP) 164 return (PS_ERR); 165 166 if (Plwp_setfpregs(P, lwpid, regs) == 0) 167 return (PS_OK); 168 169 return (PS_BADLID); 170 } 171 172 ps_err_e 173 ps_lgetxregsize(struct ps_prochandle *P, lwpid_t lwpid, int *xrsize) 174 { 175 char fname[PATH_MAX]; 176 struct stat statb; 177 178 if (P->state == PS_DEAD) { 179 core_info_t *core = P->data; 180 lwp_info_t *lwp; 181 182 for (lwp = list_head(&core->core_lwp_head); lwp != NULL; 183 lwp = list_next(&core->core_lwp_head, lwp)) { 184 if (lwp->lwp_id == lwpid) { 185 if (lwp->lwp_xregs != NULL && 186 lwp->lwp_xregsize > 0) { 187 if (lwp->lwp_xregsize >= INT_MAX) { 188 return (PS_ERR); 189 } 190 191 *xrsize = (int)lwp->lwp_xregsize; 192 } else { 193 *xrsize = 0; 194 } 195 return (PS_OK); 196 } 197 } 198 199 return (PS_BADLID); 200 } 201 202 (void) snprintf(fname, sizeof (fname), "%s/%d/lwp/%d/xregs", 203 procfs_path, (int)P->status.pr_pid, (int)lwpid); 204 205 if (stat(fname, &statb) != 0) 206 return (PS_BADLID); 207 208 if (statb.st_size > INT_MAX) 209 return (PS_ERR); 210 211 *xrsize = (int)statb.st_size; 212 return (PS_OK); 213 } 214 215 ps_err_e 216 ps_lgetxregs(struct ps_prochandle *P, lwpid_t lwpid, caddr_t xregs) 217 { 218 size_t xregsize; 219 prxregset_t *prx; 220 221 if (P->state != PS_STOP && P->state != PS_DEAD) 222 return (PS_ERR); 223 224 if (Plwp_getxregs(P, lwpid, &prx, &xregsize) == 0) { 225 (void) memcpy(xregs, prx, xregsize); 226 Plwp_freexregs(P, prx, xregsize); 227 return (PS_OK); 228 } 229 230 if (errno == ENODATA) 231 return (PS_NOXREGS); 232 else if (errno == ENOENT) 233 return (PS_BADLID); 234 return (PS_ERR); 235 } 236 237 ps_err_e 238 ps_lsetxregs(struct ps_prochandle *P, lwpid_t lwpid, caddr_t xregs) 239 { 240 size_t xregsize = 0; 241 242 if (P->state != PS_STOP) 243 return (PS_ERR); 244 245 /* 246 * libproc asks the caller for the size of the extended register set. 247 * Unfortunately, right now we aren't given the actual size of this 248 * ourselves and we don't want to break the ABI that folks have used 249 * historically. Therefore, we reach in and ask the structure in a 250 * platform-specific way about what this should be. Sorry, this is a bit 251 * unfortunate. This really shouldn't be a platform-specific #ifdef. 252 * 253 * Platforms without xregs can leave xregsize set to zero the kernel 254 * will fail with EINVAL. 255 */ 256 #if defined(__i386) || defined(__amd64) 257 prxregset_hdr_t *hdr = (prxregset_hdr_t *)xregs; 258 xregsize = hdr->pr_size; 259 #endif 260 261 if (Plwp_setxregs(P, lwpid, (prxregset_t *)xregs, xregsize) == 0) 262 return (PS_OK); 263 264 if (errno == ENOENT) 265 return (PS_BADLID); 266 return (PS_ERR); 267 } 268 269 #if defined(sparc) || defined(__sparc) 270 ps_err_e 271 ps_lsetxregs(struct ps_prochandle *P, lwpid_t lwpid, caddr_t xregs) 272 { 273 if (P->state != PS_STOP) 274 return (PS_ERR); 275 276 /* LINTED - alignment */ 277 if (Plwp_setxregs(P, lwpid, (prxregset_t *)xregs) == 0) 278 return (PS_OK); 279 280 return (PS_BADLID); 281 } 282 283 #endif /* sparc */ 284 285 #if defined(__i386) || defined(__amd64) 286 287 ps_err_e 288 ps_lgetLDT(struct ps_prochandle *P, lwpid_t lwpid, struct ssd *ldt) 289 { 290 #if defined(__amd64) && defined(_LP64) 291 if (P->status.pr_dmodel != PR_MODEL_NATIVE) { 292 #endif 293 prgregset_t regs; 294 struct ssd *ldtarray; 295 ps_err_e error; 296 uint_t gs; 297 int nldt; 298 int i; 299 300 if (P->state != PS_STOP && P->state != PS_DEAD) 301 return (PS_ERR); 302 303 /* 304 * We need to get the ldt entry that matches the 305 * value in the lwp's GS register. 306 */ 307 if ((error = ps_lgetregs(P, lwpid, regs)) != PS_OK) 308 return (error); 309 310 gs = regs[GS]; 311 312 if ((nldt = Pldt(P, NULL, 0)) <= 0 || 313 (ldtarray = malloc(nldt * sizeof (struct ssd))) == NULL) 314 return (PS_ERR); 315 if ((nldt = Pldt(P, ldtarray, nldt)) <= 0) { 316 free(ldtarray); 317 return (PS_ERR); 318 } 319 320 for (i = 0; i < nldt; i++) { 321 if (gs == ldtarray[i].sel) { 322 *ldt = ldtarray[i]; 323 break; 324 } 325 } 326 free(ldtarray); 327 328 if (i < nldt) 329 return (PS_OK); 330 #if defined(__amd64) && defined(_LP64) 331 } 332 #endif 333 334 return (PS_ERR); 335 } 336 337 #endif /* __i386 || __amd64 */ 338 339 /* 340 * Libthread_db doesn't use this function currently, but librtld_db uses 341 * it for its debugging output. We turn this on via rd_log if our debugging 342 * switch is on, and then echo the messages sent to ps_plog to stderr. 343 */ 344 void 345 ps_plog(const char *fmt, ...) 346 { 347 va_list ap; 348 349 if (_libproc_debug && fmt != NULL && *fmt != '\0') { 350 va_start(ap, fmt); 351 (void) vfprintf(stderr, fmt, ap); 352 va_end(ap); 353 if (fmt[strlen(fmt) - 1] != '\n') 354 (void) fputc('\n', stderr); 355 } 356 } 357 358 /* 359 * Store a pointer to our internal copy of the aux vector at the address 360 * specified by the caller. It should not hold on to this data for too long. 361 */ 362 ps_err_e 363 ps_pauxv(struct ps_prochandle *P, const auxv_t **aux) 364 { 365 if (P->auxv == NULL) 366 Preadauxvec(P); 367 368 if (P->auxv == NULL) 369 return (PS_ERR); 370 371 *aux = (const auxv_t *)P->auxv; 372 return (PS_OK); 373 } 374 375 ps_err_e 376 ps_pbrandname(struct ps_prochandle *P, char *buf, size_t len) 377 { 378 return (Pbrandname(P, buf, len) ? PS_OK : PS_ERR); 379 } 380 381 /* 382 * Search for a symbol by name and return the corresponding address. 383 */ 384 ps_err_e 385 ps_pglobal_lookup(struct ps_prochandle *P, const char *object_name, 386 const char *sym_name, psaddr_t *sym_addr) 387 { 388 GElf_Sym sym; 389 390 if (Plookup_by_name(P, object_name, sym_name, &sym) == 0) { 391 dprintf("pglobal_lookup <%s> -> %p\n", 392 sym_name, (void *)(uintptr_t)sym.st_value); 393 *sym_addr = (psaddr_t)sym.st_value; 394 return (PS_OK); 395 } 396 397 return (PS_NOSYM); 398 } 399 400 /* 401 * Search for a symbol by name and return the corresponding symbol 402 * information. If we're compiled _LP64, we just call Plookup_by_name 403 * and return because ps_sym_t is defined to be an Elf64_Sym, which 404 * is the same as a GElf_Sym. In the _ILP32 case, we have to convert 405 * Plookup_by_name's result back to a ps_sym_t (which is an Elf32_Sym). 406 */ 407 ps_err_e 408 ps_pglobal_sym(struct ps_prochandle *P, const char *object_name, 409 const char *sym_name, ps_sym_t *symp) 410 { 411 #if defined(_ILP32) 412 GElf_Sym sym; 413 414 if (Plookup_by_name(P, object_name, sym_name, &sym) == 0) { 415 symp->st_name = (Elf32_Word)sym.st_name; 416 symp->st_value = (Elf32_Addr)sym.st_value; 417 symp->st_size = (Elf32_Word)sym.st_size; 418 symp->st_info = ELF32_ST_INFO( 419 GELF_ST_BIND(sym.st_info), GELF_ST_TYPE(sym.st_info)); 420 symp->st_other = sym.st_other; 421 symp->st_shndx = sym.st_shndx; 422 return (PS_OK); 423 } 424 425 #elif defined(_LP64) 426 if (Plookup_by_name(P, object_name, sym_name, symp) == 0) 427 return (PS_OK); 428 #endif 429 return (PS_NOSYM); 430 } 431