devproc.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. #include "../port/edf.h"
  16. #include "tos.h"
  17. #include <trace.h>
  18. #include "ureg.h"
  19. enum
  20. {
  21. Qdir,
  22. Qtrace,
  23. Qtracepids,
  24. Qargs,
  25. Qctl,
  26. Qfd,
  27. Qfpregs,
  28. Qgdbregs,
  29. Qkregs,
  30. Qmem,
  31. Qnote,
  32. Qnoteid,
  33. Qnotepg,
  34. Qns,
  35. Qproc,
  36. Qregs,
  37. Qsegment,
  38. Qstatus,
  39. Qtext,
  40. Qwait,
  41. Qprofile,
  42. Qsyscall,
  43. Qcore,
  44. Qtls,
  45. Qpager,
  46. };
  47. enum
  48. {
  49. CMclose,
  50. CMclosefiles,
  51. CMfixedpri,
  52. CMhang,
  53. CMkill,
  54. CMnohang,
  55. CMnoswap,
  56. CMpri,
  57. CMprivate,
  58. CMprofile,
  59. CMstart,
  60. CMstartstop,
  61. CMstartsyscall,
  62. CMstop,
  63. CMwaitstop,
  64. CMwired,
  65. CMtrace,
  66. /* real time */
  67. CMperiod,
  68. CMdeadline,
  69. CMcost,
  70. CMsporadic,
  71. CMdeadlinenotes,
  72. CMadmit,
  73. CMextra,
  74. CMexpel,
  75. CMevent,
  76. CMcore,
  77. };
  78. enum{
  79. Nevents = 0x4000,
  80. Emask = Nevents - 1,
  81. Ntracedpids = 1024,
  82. };
  83. #define STATSIZE (2*KNAMELEN+NUMSIZE + 9*NUMSIZE + 6*NUMSIZE + 2*NUMSIZE + 1)
  84. /*
  85. * Status, fd, and ns are left fully readable (0444) because of their use in debugging,
  86. * particularly on shared servers.
  87. * Arguably, ns and fd shouldn't be readable; if you'd prefer, change them to 0000
  88. */
  89. Dirtab procdir[] =
  90. {
  91. "args", {Qargs}, 0, 0660,
  92. "ctl", {Qctl}, 0, 0000,
  93. "fd", {Qfd}, 0, 0444,
  94. "fpregs", {Qfpregs}, 0, 0000,
  95. "kregs", {Qkregs}, sizeof(Ureg), 0600,
  96. "mem", {Qmem}, 0, 0000,
  97. "note", {Qnote}, 0, 0000,
  98. "noteid", {Qnoteid}, 0, 0664,
  99. "notepg", {Qnotepg}, 0, 0000,
  100. "ns", {Qns}, 0, 0444,
  101. "proc", {Qproc}, 0, 0400,
  102. "gdbregs", {Qgdbregs}, GDB_NUMREGBYTES, 0000,
  103. "regs", {Qregs}, sizeof(Ureg), 0000,
  104. "segment", {Qsegment}, 0, 0444,
  105. "status", {Qstatus}, STATSIZE, 0444,
  106. "text", {Qtext}, 0, 0000,
  107. "wait", {Qwait}, 0, 0400,
  108. "profile", {Qprofile}, 0, 0400,
  109. "syscall", {Qsyscall}, 0, 0400,
  110. "core", {Qcore}, 0, 0444,
  111. "tls", {Qtls}, 0, 0600,
  112. "pager", {Qpager}, 0, 0600|DMEXCL,
  113. };
  114. static
  115. Cmdtab proccmd[] = {
  116. CMclose, "close", 2,
  117. CMclosefiles, "closefiles", 1,
  118. CMfixedpri, "fixedpri", 2,
  119. CMhang, "hang", 1,
  120. CMnohang, "nohang", 1,
  121. CMnoswap, "noswap", 1,
  122. CMkill, "kill", 1,
  123. CMpri, "pri", 2,
  124. CMprivate, "private", 1,
  125. CMprofile, "profile", 1,
  126. CMstart, "start", 1,
  127. CMstartstop, "startstop", 1,
  128. CMstartsyscall, "startsyscall", 1,
  129. CMstop, "stop", 1,
  130. CMwaitstop, "waitstop", 1,
  131. CMwired, "wired", 2,
  132. CMtrace, "trace", 0,
  133. CMperiod, "period", 2,
  134. CMdeadline, "deadline", 2,
  135. CMcost, "cost", 2,
  136. CMsporadic, "sporadic", 1,
  137. CMdeadlinenotes, "deadlinenotes", 1,
  138. CMadmit, "admit", 1,
  139. CMextra, "extra", 1,
  140. CMexpel, "expel", 1,
  141. CMevent, "event", 1,
  142. CMcore, "core", 2,
  143. };
  144. /*
  145. * Qids are, in path:
  146. * 4 bits of file type (qids above)
  147. * 23 bits of process slot number + 1
  148. * in vers,
  149. * 32 bits of pid, for consistency checking
  150. * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid.
  151. */
  152. #define QSHIFT 5 /* location in qid of proc slot # */
  153. #define SLOTBITS 23 /* number of bits in the slot */
  154. #define QIDMASK ((1<<QSHIFT)-1)
  155. #define SLOTMASK ((1<<SLOTBITS)-1 << QSHIFT)
  156. #define QID(q) ((((uint32_t)(q).path)&QIDMASK)>>0)
  157. #define SLOT(q) (((((uint32_t)(q).path)&SLOTMASK)>>QSHIFT)-1)
  158. #define PID(q) ((q).vers)
  159. #define NOTEID(q) ((q).vers)
  160. static void procctlreq(Proc*, char*, int);
  161. static int procctlmemio(Proc*, uintptr_t, int, void*, int);
  162. static Chan* proctext(Chan*, Proc*);
  163. static Segment* txt2data(Proc*, Segment*);
  164. static int procstopped(void*);
  165. static void mntscan(Mntwalk*, Proc*);
  166. static Traceevent *tevents;
  167. static char *tpids, *tpidsc, *tpidse;
  168. static Lock tlock;
  169. static int topens;
  170. static int tproduced, tconsumed;
  171. static void notrace(Proc*, int, int64_t);
  172. void (*proctrace)(Proc*, int, int64_t) = notrace;
  173. static void
  174. profclock(Ureg *ur, Timer *ti)
  175. {
  176. Proc *up = externup();
  177. Tos *tos;
  178. if(up == nil || up->state != Running)
  179. return;
  180. /* user profiling clock */
  181. if(userureg(ur)){
  182. tos = (Tos*)(USTKTOP-sizeof(Tos));
  183. tos->clock += TK2MS(1);
  184. segclock(userpc(ur));
  185. }
  186. }
  187. static int
  188. procgen(Chan *c, char *name, Dirtab *tab, int j, int s, Dir *dp)
  189. {
  190. Proc *up = externup();
  191. Qid qid;
  192. Proc *p;
  193. char *ename;
  194. int pid, sno;
  195. uint32_t path, perm, len;
  196. if(s == DEVDOTDOT){
  197. mkqid(&qid, Qdir, 0, QTDIR);
  198. devdir(c, qid, "#p", 0, eve, 0555, dp);
  199. return 1;
  200. }
  201. if(c->qid.path == Qdir){
  202. if(s == 0){
  203. strcpy(up->genbuf, "trace");
  204. mkqid(&qid, Qtrace, -1, QTFILE);
  205. devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
  206. return 1;
  207. }
  208. if(s == 1){
  209. strcpy(up->genbuf, "tracepids");
  210. mkqid(&qid, Qtracepids, -1, QTFILE);
  211. devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
  212. return 1;
  213. }
  214. s -= 2;
  215. if(name != nil){
  216. /* ignore s and use name to find pid */
  217. pid = strtol(name, &ename, 10);
  218. if(pid<=0 || ename[0]!='\0')
  219. return -1;
  220. s = psindex(pid);
  221. if(s < 0)
  222. return -1;
  223. }
  224. else if(s >= conf.nproc)
  225. return -1;
  226. if((p = psincref(s)) == nil || (pid = p->pid) == 0)
  227. return 0;
  228. snprint(up->genbuf, sizeof up->genbuf, "%u", pid);
  229. /*
  230. * String comparison is done in devwalk so
  231. * name must match its formatted pid.
  232. */
  233. if(name != nil && strcmp(name, up->genbuf) != 0)
  234. return -1;
  235. mkqid(&qid, (s+1)<<QSHIFT, pid, QTDIR);
  236. devdir(c, qid, up->genbuf, 0, p->user, DMDIR|0555, dp);
  237. psdecref(p);
  238. return 1;
  239. }
  240. if(c->qid.path == Qtrace){
  241. strcpy(up->genbuf, "trace");
  242. mkqid(&qid, Qtrace, -1, QTFILE);
  243. devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
  244. return 1;
  245. }
  246. if(c->qid.path == Qtracepids){
  247. strcpy(up->genbuf, "tracepids");
  248. mkqid(&qid, Qtrace, -1, QTFILE);
  249. devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
  250. return 1;
  251. }
  252. if(s >= nelem(procdir))
  253. return -1;
  254. if(tab)
  255. panic("procgen");
  256. tab = &procdir[s];
  257. path = c->qid.path&~(((1<<QSHIFT)-1)); /* slot component */
  258. if((p = psincref(SLOT(c->qid))) == nil)
  259. return -1;
  260. perm = tab->perm;
  261. if(perm == 0)
  262. perm = p->procmode;
  263. else /* just copy read bits */
  264. perm |= p->procmode & 0444;
  265. len = tab->length;
  266. switch(QID(c->qid)) {
  267. case Qwait:
  268. len = p->nwait; /* incorrect size, but >0 means there's something to read */
  269. break;
  270. case Qprofile: /* TODO(aki): test this */
  271. len = 0;
  272. for(sno = 0; sno < NSEG; sno++){
  273. if(p->seg[sno] != nil && (p->seg[sno]->type & SG_EXEC) != 0){
  274. Segment *s;
  275. s = p->seg[sno];
  276. if(s->profile)
  277. len += ((s->top-s->base)>>LRESPROF) * sizeof s->profile[0];
  278. }
  279. }
  280. break;
  281. }
  282. mkqid(&qid, path|tab->qid.path, c->qid.vers, QTFILE);
  283. devdir(c, qid, tab->name, len, p->user, perm, dp);
  284. psdecref(p);
  285. return 1;
  286. }
  287. static void
  288. notrace(Proc* p, int n, int64_t m)
  289. {
  290. }
  291. static Lock tlck;
  292. static void
  293. _proctrace(Proc* p, int etype, int64_t ts)
  294. {
  295. Traceevent *te;
  296. int tp;
  297. ilock(&tlck);
  298. if (p->trace == 0 || topens == 0 ||
  299. tproduced - tconsumed >= Nevents){
  300. iunlock(&tlck);
  301. return;
  302. }
  303. tp = tproduced++;
  304. iunlock(&tlck);
  305. te = &tevents[tp&Emask];
  306. te->pid = p->pid;
  307. te->etype = etype;
  308. if (ts == 0)
  309. te->time = todget(nil);
  310. else
  311. te->time = ts;
  312. te->core = machp()->machno;
  313. }
  314. void
  315. proctracepid(Proc *p)
  316. {
  317. if(p->trace == 1 && proctrace != notrace){
  318. p->trace = 2;
  319. ilock(&tlck);
  320. tpidsc = seprint(tpidsc, tpidse, "%d %s\n", p->pid, p->text);
  321. iunlock(&tlck);
  322. }
  323. }
  324. static void
  325. procinit(void)
  326. {
  327. if(conf.nproc >= (SLOTMASK>>QSHIFT) - 1)
  328. print("warning: too many procs for devproc\n");
  329. addclock0link((void (*)(void))profclock, 113); /* Relative prime to HZ */
  330. }
  331. static Chan*
  332. procattach(char *spec)
  333. {
  334. return devattach('p', spec);
  335. }
  336. static Walkqid*
  337. procwalk(Chan *c, Chan *nc, char **name, int nname)
  338. {
  339. return devwalk(c, nc, name, nname, 0, 0, procgen);
  340. }
  341. static int32_t
  342. procstat(Chan *c, uint8_t *db, int32_t n)
  343. {
  344. return devstat(c, db, n, 0, 0, procgen);
  345. }
  346. /*
  347. * none can't read or write state on other
  348. * processes. This is to contain access of
  349. * servers running as none should they be
  350. * subverted by, for example, a stack attack.
  351. */
  352. static void
  353. nonone(Proc *p)
  354. {
  355. Proc *up = externup();
  356. if(p == up)
  357. return;
  358. if(strcmp(up->user, "none") != 0)
  359. return;
  360. if(iseve())
  361. return;
  362. error(Eperm);
  363. }
  364. static Chan*
  365. procopen(Chan *c, int omode)
  366. {
  367. Proc *up = externup();
  368. Proc *p;
  369. Pgrp *pg;
  370. Chan *tc;
  371. int pid;
  372. if(c->qid.type & QTDIR)
  373. return devopen(c, omode, 0, 0, procgen);
  374. if(QID(c->qid) == Qtrace){
  375. if (omode != OREAD)
  376. error(Eperm);
  377. lock(&tlock);
  378. if (waserror()){
  379. unlock(&tlock);
  380. nexterror();
  381. }
  382. if (topens > 0)
  383. error("already open");
  384. topens++;
  385. if (tevents == nil){
  386. tevents = (Traceevent*)malloc(sizeof(Traceevent) * Nevents);
  387. if(tevents == nil)
  388. error(Enomem);
  389. tpids = malloc(Ntracedpids * 20);
  390. if(tpids == nil){
  391. free(tpids);
  392. tpids = nil;
  393. error(Enomem);
  394. }
  395. tpidsc = tpids;
  396. tpidse = tpids + Ntracedpids * 20;
  397. *tpidsc = 0;
  398. tproduced = tconsumed = 0;
  399. }
  400. proctrace = _proctrace;
  401. poperror();
  402. unlock(&tlock);
  403. c->mode = openmode(omode);
  404. c->flag |= COPEN;
  405. c->offset = 0;
  406. return c;
  407. }
  408. if(QID(c->qid) == Qtracepids){
  409. if (omode != OREAD)
  410. error(Eperm);
  411. c->mode = openmode(omode);
  412. c->flag |= COPEN;
  413. c->offset = 0;
  414. return c;
  415. }
  416. if((p = psincref(SLOT(c->qid))) == nil)
  417. error(Eprocdied);
  418. qlock(&p->debug);
  419. if(waserror()){
  420. qunlock(&p->debug);
  421. psdecref(p);
  422. nexterror();
  423. }
  424. pid = PID(c->qid);
  425. if(p->pid != pid)
  426. error(Eprocdied);
  427. omode = openmode(omode);
  428. switch(QID(c->qid)){
  429. case Qtext:
  430. if(omode != OREAD)
  431. error(Eperm);
  432. tc = proctext(c, p);
  433. tc->offset = 0;
  434. poperror();
  435. qunlock(&p->debug);
  436. psdecref(p);
  437. cclose(c);
  438. return tc;
  439. case Qproc:
  440. case Qkregs:
  441. case Qsegment:
  442. case Qprofile:
  443. case Qfd:
  444. if(omode != OREAD)
  445. error(Eperm);
  446. break;
  447. case Qnote:
  448. if(p->privatemem)
  449. error(Eperm);
  450. break;
  451. case Qmem:
  452. case Qctl:
  453. if(p->privatemem)
  454. error(Eperm);
  455. nonone(p);
  456. break;
  457. case Qtls:
  458. if(p->pid != up->pid)
  459. error(Eperm);
  460. nonone(p);
  461. break;
  462. case Qargs:
  463. case Qnoteid:
  464. case Qstatus:
  465. case Qwait:
  466. case Qgdbregs:
  467. case Qregs:
  468. case Qfpregs:
  469. case Qsyscall:
  470. case Qcore:
  471. nonone(p);
  472. break;
  473. case Qpager:
  474. p->resp = qopen(1024, Qmsg, nil, 0);
  475. p->req = qopen(1024, Qmsg, nil, 0);
  476. print("p %d sets resp %p req %p\n", p->pid, p->resp, p->req);
  477. c->aux = p;
  478. break;
  479. case Qns:
  480. if(omode != OREAD)
  481. error(Eperm);
  482. c->aux = malloc(sizeof(Mntwalk));
  483. break;
  484. case Qnotepg:
  485. nonone(p);
  486. pg = p->pgrp;
  487. if(pg == nil)
  488. error(Eprocdied);
  489. if(omode!=OWRITE || pg->pgrpid == 1)
  490. error(Eperm);
  491. c->pgrpid.path = pg->pgrpid+1;
  492. c->pgrpid.vers = p->noteid;
  493. break;
  494. default:
  495. poperror();
  496. qunlock(&p->debug);
  497. psdecref(p);
  498. pprint("procopen %#llx\n", c->qid.path);
  499. error(Egreg);
  500. }
  501. /* Affix pid to qid */
  502. if(p->state != Dead)
  503. c->qid.vers = p->pid;
  504. /* make sure the process slot didn't get reallocated while we were playing */
  505. coherence();
  506. if(p->pid != pid)
  507. error(Eprocdied);
  508. tc = devopen(c, omode, 0, 0, procgen);
  509. poperror();
  510. qunlock(&p->debug);
  511. psdecref(p);
  512. return tc;
  513. }
  514. static int32_t
  515. procwstat(Chan *c, uint8_t *db, int32_t n)
  516. {
  517. Proc *up = externup();
  518. Proc *p;
  519. Dir *d;
  520. if(c->qid.type & QTDIR)
  521. error(Eperm);
  522. if(QID(c->qid) == Qtrace)
  523. return devwstat(c, db, n);
  524. if((p = psincref(SLOT(c->qid))) == nil)
  525. error(Eprocdied);
  526. nonone(p);
  527. d = nil;
  528. qlock(&p->debug);
  529. if(waserror()){
  530. qunlock(&p->debug);
  531. psdecref(p);
  532. free(d);
  533. nexterror();
  534. }
  535. if(p->pid != PID(c->qid))
  536. error(Eprocdied);
  537. if(strcmp(up->user, p->user) != 0 && strcmp(up->user, eve) != 0)
  538. error(Eperm);
  539. d = smalloc(sizeof(Dir)+n);
  540. n = convM2D(db, n, &d[0], (char*)&d[1]);
  541. if(n == 0)
  542. error(Eshortstat);
  543. if(!emptystr(d->uid) && strcmp(d->uid, p->user) != 0){
  544. if(strcmp(up->user, eve) != 0)
  545. error(Eperm);
  546. else
  547. kstrdup(&p->user, d->uid);
  548. }
  549. if(d->mode != (uint32_t)~0UL)
  550. p->procmode = d->mode&0777;
  551. poperror();
  552. qunlock(&p->debug);
  553. psdecref(p);
  554. free(d);
  555. return n;
  556. }
  557. static int32_t
  558. procoffset(int32_t offset, char *va, int *np)
  559. {
  560. if(offset > 0) {
  561. offset -= *np;
  562. if(offset < 0) {
  563. memmove(va, va+*np+offset, -offset);
  564. *np = -offset;
  565. }
  566. else
  567. *np = 0;
  568. }
  569. return offset;
  570. }
  571. static int
  572. procqidwidth(Chan *c)
  573. {
  574. char buf[32];
  575. return sprint(buf, "%lu", c->qid.vers);
  576. }
  577. int
  578. procfdprint(Chan *c, int fd, int w, char *s, int ns)
  579. {
  580. int n;
  581. if(w == 0)
  582. w = procqidwidth(c);
  583. n = snprint(s, ns, "%3d %.2s %C %4ud (%.16llx %*lu %.2x) %5ld %8lld %s\n",
  584. fd,
  585. &"r w rw"[(c->mode&3)<<1],
  586. c->dev->dc, c->devno,
  587. c->qid.path, w, c->qid.vers, c->qid.type,
  588. c->iounit, c->offset, c->path->s);
  589. return n;
  590. }
  591. static int
  592. procfds(Proc *p, char *va, int count, int32_t offset)
  593. {
  594. Proc *up = externup();
  595. Fgrp *f;
  596. Chan *c;
  597. char buf[256];
  598. int n, i, w, ww;
  599. char *a;
  600. /* print to buf to avoid holding fgrp lock while writing to user space */
  601. if(count > sizeof buf)
  602. count = sizeof buf;
  603. a = buf;
  604. qlock(&p->debug);
  605. f = p->fgrp;
  606. if(f == nil){
  607. qunlock(&p->debug);
  608. return 0;
  609. }
  610. lock(&f->r.l);
  611. if(waserror()){
  612. unlock(&f->r.l);
  613. qunlock(&p->debug);
  614. nexterror();
  615. }
  616. n = readstr(0, a, count, p->dot->path->s);
  617. n += snprint(a+n, count-n, "\n");
  618. offset = procoffset(offset, a, &n);
  619. /* compute width of qid.path */
  620. w = 0;
  621. for(i = 0; i <= f->maxfd; i++) {
  622. c = f->fd[i];
  623. if(c == nil)
  624. continue;
  625. ww = procqidwidth(c);
  626. if(ww > w)
  627. w = ww;
  628. }
  629. for(i = 0; i <= f->maxfd; i++) {
  630. c = f->fd[i];
  631. if(c == nil)
  632. continue;
  633. n += procfdprint(c, i, w, a+n, count-n);
  634. offset = procoffset(offset, a, &n);
  635. }
  636. poperror();
  637. unlock(&f->r.l);
  638. qunlock(&p->debug);
  639. /* copy result to user space, now that locks are released */
  640. memmove(va, buf, n);
  641. return n;
  642. }
  643. static void
  644. procclose(Chan * c)
  645. {
  646. if(QID(c->qid) == Qtrace){
  647. lock(&tlock);
  648. if(topens > 0)
  649. topens--;
  650. if(topens == 0)
  651. proctrace = notrace;
  652. unlock(&tlock);
  653. }
  654. if(QID(c->qid) == Qpager){
  655. print("leaking queueus for pager\n");
  656. }
  657. if(QID(c->qid) == Qns && c->aux != 0)
  658. free(c->aux);
  659. }
  660. static void
  661. int2flag(int flag, char *s)
  662. {
  663. if(flag == 0){
  664. *s = '\0';
  665. return;
  666. }
  667. *s++ = '-';
  668. if(flag & MAFTER)
  669. *s++ = 'a';
  670. if(flag & MBEFORE)
  671. *s++ = 'b';
  672. if(flag & MCREATE)
  673. *s++ = 'c';
  674. if(flag & MCACHE)
  675. *s++ = 'C';
  676. *s = '\0';
  677. }
  678. static int
  679. procargs(Proc *p, char *buf, int nbuf)
  680. {
  681. int j, k, m;
  682. char *a;
  683. int n;
  684. a = p->args;
  685. if(p->setargs){
  686. snprint(buf, nbuf, "%s [%s]", p->text, p->args);
  687. return strlen(buf);
  688. }
  689. n = p->nargs;
  690. for(j = 0; j < nbuf - 1; j += m){
  691. if(n <= 0)
  692. break;
  693. if(j != 0)
  694. buf[j++] = ' ';
  695. m = snprint(buf+j, nbuf-j, "%q", a);
  696. k = strlen(a) + 1;
  697. a += k;
  698. n -= k;
  699. }
  700. return j;
  701. }
  702. static int
  703. eventsavailable(void *v)
  704. {
  705. return tproduced > tconsumed;
  706. }
  707. static int32_t
  708. procread(Chan *c, void *va, int32_t n, int64_t off)
  709. {
  710. Proc *up = externup();
  711. Proc *p;
  712. Mach *ac, *wired;
  713. int32_t l, r;
  714. Waitq *wq;
  715. Ureg kur;
  716. uint8_t *rptr;
  717. Confmem *cm;
  718. Mntwalk *mw;
  719. Segment *sg, *s;
  720. int i, j, navail, pid, rsize, sno;
  721. char flag[10], *sps, *srv, *statbuf;
  722. uintptr_t offset, profoff, u;
  723. int tesz;
  724. uintptr_t gdbregs[DBG_MAX_REG_NUM];
  725. if(c->qid.type & QTDIR)
  726. return devdirread(c, va, n, 0, 0, procgen);
  727. offset = off;
  728. if(QID(c->qid) == Qtrace){
  729. if(!eventsavailable(nil))
  730. return 0;
  731. rptr = va;
  732. tesz = BIT32SZ + BIT32SZ + BIT64SZ + BIT32SZ;
  733. navail = tproduced - tconsumed;
  734. if(navail > n / tesz)
  735. navail = n / tesz;
  736. while(navail > 0) {
  737. PBIT32(rptr, tevents[tconsumed & Emask].pid);
  738. rptr += BIT32SZ;
  739. PBIT32(rptr, tevents[tconsumed & Emask].etype);
  740. rptr += BIT32SZ;
  741. PBIT64(rptr, tevents[tconsumed & Emask].time);
  742. rptr += BIT64SZ;
  743. PBIT32(rptr, tevents[tconsumed & Emask].core);
  744. rptr += BIT32SZ;
  745. tconsumed++;
  746. navail--;
  747. }
  748. return rptr - (uint8_t*)va;
  749. }
  750. if(QID(c->qid) == Qtracepids)
  751. if(tpids == nil)
  752. return 0;
  753. else
  754. return readstr(off, va, n, tpids);
  755. if((p = psincref(SLOT(c->qid))) == nil || p->pid != PID(c->qid))
  756. error(Eprocdied);
  757. switch(QID(c->qid)){
  758. default:
  759. psdecref(p);
  760. break;
  761. case Qargs:
  762. qlock(&p->debug);
  763. j = procargs(p, up->genbuf, sizeof up->genbuf);
  764. qunlock(&p->debug);
  765. psdecref(p);
  766. if(offset >= j)
  767. return 0;
  768. if(offset+n > j)
  769. n = j-offset;
  770. memmove(va, &up->genbuf[offset], n);
  771. return n;
  772. case Qsyscall:
  773. if(p->syscalltrace == nil)
  774. return 0;
  775. return readstr(offset, va, n, p->syscalltrace);
  776. case Qcore:
  777. i = 0;
  778. ac = p->ac;
  779. wired = p->wired;
  780. if(ac != nil)
  781. i = ac->machno;
  782. else if(wired != nil)
  783. i = wired->machno;
  784. statbuf = smalloc(STATSIZE);
  785. snprint(statbuf, STATSIZE, "%d\n", i);
  786. n = readstr(offset, va, n, statbuf);
  787. free(statbuf);
  788. return n;
  789. case Qmem:
  790. if(offset < KZERO || (offset >= USTKTOP-USTKSIZE && offset < USTKTOP)){
  791. r = procctlmemio(p, offset, n, va, 1);
  792. psdecref(p);
  793. return r;
  794. }
  795. if(!iseve()){
  796. psdecref(p);
  797. error(Eperm);
  798. }
  799. /* validate kernel addresses */
  800. if(offset < PTR2UINT(end)) {
  801. if(offset+n > PTR2UINT(end))
  802. n = PTR2UINT(end) - offset;
  803. memmove(va, UINT2PTR(offset), n);
  804. psdecref(p);
  805. return n;
  806. }
  807. for(i=0; i<nelem(conf.mem); i++){
  808. cm = &conf.mem[i];
  809. /* klimit-1 because klimit might be zero! */
  810. if(cm->kbase <= offset && offset <= cm->klimit-1){
  811. if(offset+n >= cm->klimit-1)
  812. n = cm->klimit - offset;
  813. memmove(va, UINT2PTR(offset), n);
  814. psdecref(p);
  815. return n;
  816. }
  817. }
  818. psdecref(p);
  819. error(Ebadarg);
  820. case Qprofile:
  821. profoff = 0;
  822. for(sno = 0; sno < NSEG; sno++){
  823. if(p->seg[sno] == nil)
  824. continue;
  825. if((p->seg[sno]->type & SG_EXEC) == 0)
  826. continue;
  827. if(p->seg[sno]->profile == nil)
  828. continue;
  829. s = p->seg[sno];
  830. i = ((s->top-s->base)>>LRESPROF) * sizeof s->profile[0];
  831. if(offset >= profoff+i){
  832. profoff += i;
  833. continue;
  834. }
  835. if(offset+n > profoff+i)
  836. n = profoff+i - offset;
  837. memmove(va, ((char*)s->profile)+(offset-profoff), n);
  838. psdecref(p);
  839. return n;
  840. }
  841. psdecref(p);
  842. if(sno == NSEG)
  843. error("profile is off");
  844. return 0;
  845. case Qnote:
  846. qlock(&p->debug);
  847. if(waserror()){
  848. qunlock(&p->debug);
  849. psdecref(p);
  850. nexterror();
  851. }
  852. if(p->pid != PID(c->qid))
  853. error(Eprocdied);
  854. if(n < 1) /* must accept at least the '\0' */
  855. error(Etoosmall);
  856. if(p->nnote == 0)
  857. n = 0;
  858. else {
  859. i = strlen(p->note[0].msg) + 1;
  860. if(i > n)
  861. i = n;
  862. rptr = va;
  863. memmove(rptr, p->note[0].msg, i);
  864. rptr[i-1] = '\0';
  865. p->nnote--;
  866. memmove(p->note, p->note+1, p->nnote*sizeof(Note));
  867. n = i;
  868. }
  869. if(p->nnote == 0)
  870. p->notepending = 0;
  871. poperror();
  872. qunlock(&p->debug);
  873. psdecref(p);
  874. return n;
  875. case Qproc:
  876. if(offset >= sizeof(Proc)){
  877. psdecref(p);
  878. return 0;
  879. }
  880. if(offset+n > sizeof(Proc))
  881. n = sizeof(Proc) - offset;
  882. memmove(va, ((char*)p)+offset, n);
  883. psdecref(p);
  884. return n;
  885. case Qregs:
  886. rptr = (uint8_t*)p->dbgreg;
  887. rsize = sizeof(Ureg);
  888. regread:
  889. if(rptr == 0){
  890. psdecref(p);
  891. error(Enoreg);
  892. }
  893. if(offset >= rsize){
  894. psdecref(p);
  895. return 0;
  896. }
  897. if(offset+n > rsize)
  898. n = rsize - offset;
  899. memmove(va, rptr+offset, n);
  900. psdecref(p);
  901. return n;
  902. /* Sorry about the code duplication. TODO: clean this up? */
  903. case Qgdbregs:
  904. rptr = (uint8_t*)&gdbregs[0];
  905. // not sizeof; it's an odd number of 32-bit words ... yuck.
  906. rsize = GDB_NUMREGBYTES;
  907. if(rptr == 0){
  908. psdecref(p);
  909. error(Enoreg);
  910. }
  911. if(offset >= rsize){
  912. psdecref(p);
  913. return 0;
  914. }
  915. if(offset+n > rsize)
  916. n = rsize - offset;
  917. ureg2gdb(p->dbgreg, gdbregs);
  918. print("Qgdbregs: va %p, rptr +offset %p, n %d\n", va, rptr+offset, n);
  919. memmove(va, rptr+offset, n);
  920. psdecref(p);
  921. return n;
  922. case Qkregs:
  923. memset(&kur, 0, sizeof(Ureg));
  924. setkernur(&kur, p);
  925. rptr = (uint8_t*)&kur;
  926. rsize = sizeof(Ureg);
  927. goto regread;
  928. case Qfpregs:
  929. r = fpudevprocio(p, va, n, offset, 0);
  930. psdecref(p);
  931. return r;
  932. case Qstatus:
  933. if(offset >= STATSIZE){
  934. psdecref(p);
  935. return 0;
  936. }
  937. if(offset+n > STATSIZE)
  938. n = STATSIZE - offset;
  939. sps = p->psstate;
  940. if(sps == 0)
  941. sps = statename[p->state];
  942. statbuf = smalloc(STATSIZE);
  943. memset(statbuf, ' ', STATSIZE);
  944. sprint(statbuf, "%-*.*s%-*.*s%-12.11s",
  945. KNAMELEN, KNAMELEN-1, p->text,
  946. KNAMELEN, KNAMELEN-1, p->user,
  947. sps);
  948. j = 2*KNAMELEN + 12;
  949. for(i = 0; i < 6; i++) {
  950. l = p->time[i];
  951. if(i == TReal)
  952. l = sys->ticks - l;
  953. l = TK2MS(l);
  954. readnum(0, statbuf+j+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
  955. }
  956. /* ignore stacks, which are typically not faulted in */
  957. u = 0;
  958. for(i=0; i<NSEG; i++){
  959. s = p->seg[i];
  960. if(s != nil && (s->type&SG_TYPE) != SG_STACK)
  961. u += s->top - s->base;
  962. }
  963. readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, u>>10u, NUMSIZE); /* wrong size */
  964. readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->basepri, NUMSIZE);
  965. readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->priority, NUMSIZE);
  966. /*
  967. * NIX: added # of traps, syscalls, and iccs
  968. */
  969. readnum(0, statbuf+j+NUMSIZE*9, NUMSIZE, p->ntrap, NUMSIZE);
  970. readnum(0, statbuf+j+NUMSIZE*10, NUMSIZE, p->nintr, NUMSIZE);
  971. readnum(0, statbuf+j+NUMSIZE*11, NUMSIZE, p->nsyscall, NUMSIZE);
  972. readnum(0, statbuf+j+NUMSIZE*12, NUMSIZE, p->nicc, NUMSIZE);
  973. readnum(0, statbuf+j+NUMSIZE*13, NUMSIZE, p->nactrap, NUMSIZE);
  974. readnum(0, statbuf+j+NUMSIZE*14, NUMSIZE, p->nacsyscall, NUMSIZE);
  975. /*
  976. * external pager support, random stuff.
  977. */
  978. if (0) print("qstatus p %p pid %d req %p\n", p, p->pid, p->req);
  979. readnum(0,statbuf+j+NUMSIZE*15, NUMSIZE, p->req ? 1 : 0, NUMSIZE);
  980. readnum(0,statbuf+j+NUMSIZE*16, NUMSIZE, p->resp ? 1 : 0, NUMSIZE);
  981. statbuf[j+NUMSIZE*17] = '\n';
  982. if(offset+n > j+NUMSIZE*17+1)
  983. n = j+NUMSIZE*17+1-offset;
  984. memmove(va, statbuf+offset, n);
  985. free(statbuf);
  986. psdecref(p);
  987. return n;
  988. case Qsegment:
  989. j = 0;
  990. statbuf = smalloc(STATSIZE);
  991. for(i = 0; i < NSEG; i++) {
  992. sg = p->seg[i];
  993. if(sg == 0)
  994. continue;
  995. j += sprint(statbuf+j, "%-6s %c%c%c %c %p %p %4d\n",
  996. segtypes[sg->type&SG_TYPE],
  997. (sg->type&SG_READ) != 0 ? 'r' : '-',
  998. (sg->type&SG_WRITE) != 0 ? 'w' : '-',
  999. (sg->type&SG_EXEC) != 0 ? 'x' : '-',
  1000. sg->profile ? 'P' : ' ',
  1001. sg->base, sg->top, sg->r.ref);
  1002. }
  1003. psdecref(p);
  1004. if(offset >= j){
  1005. free(statbuf);
  1006. return 0;
  1007. }
  1008. if(offset+n > j)
  1009. n = j-offset;
  1010. if(n == 0 && offset == 0){
  1011. free(statbuf);
  1012. exhausted("segments");
  1013. }
  1014. memmove(va, statbuf+offset, n);
  1015. free(statbuf);
  1016. return n;
  1017. case Qwait:
  1018. if(!canqlock(&p->qwaitr)){
  1019. psdecref(p);
  1020. error(Einuse);
  1021. }
  1022. if(waserror()) {
  1023. qunlock(&p->qwaitr);
  1024. psdecref(p);
  1025. nexterror();
  1026. }
  1027. lock(&p->exl);
  1028. if(up == p && p->nchild == 0 && p->waitq == 0) {
  1029. unlock(&p->exl);
  1030. error(Enochild);
  1031. }
  1032. pid = p->pid;
  1033. while(p->waitq == 0) {
  1034. unlock(&p->exl);
  1035. sleep(&p->waitr, haswaitq, p);
  1036. if(p->pid != pid)
  1037. error(Eprocdied);
  1038. lock(&p->exl);
  1039. }
  1040. wq = p->waitq;
  1041. p->waitq = wq->next;
  1042. p->nwait--;
  1043. unlock(&p->exl);
  1044. poperror();
  1045. qunlock(&p->qwaitr);
  1046. psdecref(p);
  1047. n = snprint(va, n, "%d %lu %lu %lu %q",
  1048. wq->w.pid,
  1049. wq->w.time[TUser], wq->w.time[TSys], wq->w.time[TReal],
  1050. wq->w.msg);
  1051. free(wq);
  1052. return n;
  1053. case Qns:
  1054. qlock(&p->debug);
  1055. if(waserror()){
  1056. qunlock(&p->debug);
  1057. psdecref(p);
  1058. nexterror();
  1059. }
  1060. if(p->pgrp == nil || p->pid != PID(c->qid))
  1061. error(Eprocdied);
  1062. mw = c->aux;
  1063. if(mw->cddone){
  1064. poperror();
  1065. qunlock(&p->debug);
  1066. psdecref(p);
  1067. return 0;
  1068. }
  1069. mntscan(mw, p);
  1070. if(mw->mh == 0){
  1071. mw->cddone = 1;
  1072. i = snprint(va, n, "cd %s\n", p->dot->path->s);
  1073. poperror();
  1074. qunlock(&p->debug);
  1075. psdecref(p);
  1076. return i;
  1077. }
  1078. int2flag(mw->cm->mflag, flag);
  1079. if(strcmp(mw->cm->to->path->s, "#M") == 0){
  1080. srv = srvname(mw->cm->to->mchan);
  1081. i = snprint(va, n, "mount %s %s %s %s\n", flag,
  1082. srv==nil? mw->cm->to->mchan->path->s : srv,
  1083. mw->mh->from->path->s, mw->cm->spec? mw->cm->spec : "");
  1084. free(srv);
  1085. }else
  1086. i = snprint(va, n, "bind %s %s %s\n", flag,
  1087. mw->cm->to->path->s, mw->mh->from->path->s);
  1088. poperror();
  1089. qunlock(&p->debug);
  1090. psdecref(p);
  1091. return i;
  1092. case Qnoteid:
  1093. r = readnum(offset, va, n, p->noteid, NUMSIZE);
  1094. psdecref(p);
  1095. return r;
  1096. case Qfd:
  1097. r = procfds(p, va, n, offset);
  1098. psdecref(p);
  1099. return r;
  1100. case Qtls:
  1101. statbuf = smalloc(STATSIZE);
  1102. j = snprint(statbuf, STATSIZE, "tls 0x%p\n", p->tls);
  1103. psdecref(p);
  1104. if(offset >= j){
  1105. free(statbuf);
  1106. return 0;
  1107. }
  1108. if(offset+n > j)
  1109. n = j-offset;
  1110. memmove(va, statbuf+offset, n);
  1111. free(statbuf);
  1112. return n;
  1113. case Qpager:
  1114. p = c->aux;
  1115. n = qread(p->req, va, n);
  1116. print("read pager: %p\n", n);
  1117. break;
  1118. }
  1119. error(Egreg);
  1120. return 0; /* not reached */
  1121. }
  1122. static void
  1123. mntscan(Mntwalk *mw, Proc *p)
  1124. {
  1125. Pgrp *pg;
  1126. Mount *t;
  1127. Mhead *f;
  1128. int best, i, last, nxt;
  1129. pg = p->pgrp;
  1130. rlock(&pg->ns);
  1131. nxt = 0;
  1132. best = (int)(~0U>>1); /* largest 2's complement int */
  1133. last = 0;
  1134. if(mw->mh)
  1135. last = mw->cm->mountid;
  1136. for(i = 0; i < MNTHASH; i++) {
  1137. for(f = pg->mnthash[i]; f; f = f->hash) {
  1138. for(t = f->mount; t; t = t->next) {
  1139. if(mw->mh == 0 ||
  1140. (t->mountid > last && t->mountid < best)) {
  1141. mw->cm = t;
  1142. mw->mh = f;
  1143. best = mw->cm->mountid;
  1144. nxt = 1;
  1145. }
  1146. }
  1147. }
  1148. }
  1149. if(nxt == 0)
  1150. mw->mh = 0;
  1151. runlock(&pg->ns);
  1152. }
  1153. static int32_t
  1154. procwrite(Chan *c, void *va, int32_t n, int64_t off)
  1155. {
  1156. Proc *up = externup();
  1157. Proc *p, *t;
  1158. int i, id, l;
  1159. char *args, buf[ERRMAX];
  1160. uintptr_t offset;
  1161. if(c->qid.type & QTDIR)
  1162. error(Eisdir);
  1163. /* Use the remembered noteid in the channel rather
  1164. * than the process pgrpid
  1165. */
  1166. if(QID(c->qid) == Qnotepg) {
  1167. pgrpnote(NOTEID(c->pgrpid), va, n, NUser);
  1168. return n;
  1169. }
  1170. if((p = psincref(SLOT(c->qid))) == nil)
  1171. error(Eprocdied);
  1172. qlock(&p->debug);
  1173. if(waserror()){
  1174. qunlock(&p->debug);
  1175. psdecref(p);
  1176. nexterror();
  1177. }
  1178. if(p->pid != PID(c->qid))
  1179. error(Eprocdied);
  1180. offset = off;
  1181. switch(QID(c->qid)){
  1182. case Qargs:
  1183. if(n == 0)
  1184. error(Eshort);
  1185. if(n >= ERRMAX)
  1186. error(Etoobig);
  1187. memmove(buf, va, n);
  1188. args = malloc(n+1);
  1189. if(args == nil)
  1190. error(Enomem);
  1191. memmove(args, buf, n);
  1192. l = n;
  1193. if(args[l-1] != 0)
  1194. args[l++] = 0;
  1195. free(p->args);
  1196. p->nargs = l;
  1197. p->args = args;
  1198. p->setargs = 1;
  1199. break;
  1200. case Qmem:
  1201. if(p->state != Stopped)
  1202. error(Ebadctl);
  1203. n = procctlmemio(p, offset, n, va, 0);
  1204. break;
  1205. case Qregs:
  1206. if(offset >= sizeof(Ureg))
  1207. n = 0;
  1208. else if(offset+n > sizeof(Ureg))
  1209. n = sizeof(Ureg) - offset;
  1210. if(p->dbgreg == 0)
  1211. error(Enoreg);
  1212. setregisters(p->dbgreg, (char*)(p->dbgreg)+offset, va, n);
  1213. break;
  1214. case Qfpregs:
  1215. n = fpudevprocio(p, va, n, offset, 1);
  1216. break;
  1217. case Qctl:
  1218. procctlreq(p, va, n);
  1219. break;
  1220. case Qnote:
  1221. if(p->kp)
  1222. error(Eperm);
  1223. if(n >= ERRMAX-1)
  1224. error(Etoobig);
  1225. memmove(buf, va, n);
  1226. buf[n] = 0;
  1227. if(!postnote(p, 0, buf, NUser))
  1228. error("note not posted");
  1229. break;
  1230. case Qnoteid:
  1231. id = atoi(va);
  1232. if(id == p->pid) {
  1233. p->noteid = id;
  1234. break;
  1235. }
  1236. for(i = 0; (t = psincref(i)) != nil; i++){
  1237. if(t->state == Dead || t->noteid != id){
  1238. psdecref(t);
  1239. continue;
  1240. }
  1241. if(strcmp(p->user, t->user) != 0){
  1242. psdecref(t);
  1243. error(Eperm);
  1244. }
  1245. psdecref(t);
  1246. p->noteid = id;
  1247. break;
  1248. }
  1249. if(p->noteid != id)
  1250. error(Ebadarg);
  1251. break;
  1252. case Qtls:
  1253. if(n >= sizeof buf)
  1254. error(Etoobig);
  1255. memmove(buf, va, n);
  1256. buf[n] = '\0';
  1257. if(memcmp(buf, "tls ", 4) == 0){
  1258. char *s;
  1259. for(s = buf; *s != '\0' && (*s < '0' || *s > '9'); s++)
  1260. ;
  1261. if(*s >= '0' && *s <= '9'){
  1262. p->tls = (uintptr_t)strtoull(s, nil, 0); // a-tol-whex! a-tol-whex!
  1263. poperror();
  1264. qunlock(&p->debug);
  1265. psdecref(p);
  1266. return n;
  1267. }
  1268. }
  1269. error(Ebadarg);
  1270. case Qpager:
  1271. p = c->aux;
  1272. if (p && p->resp)
  1273. n = qwrite(p->resp, va, n);
  1274. break;
  1275. default:
  1276. poperror();
  1277. qunlock(&p->debug);
  1278. psdecref(p);
  1279. pprint("unknown qid %#llx in procwrite\n", c->qid.path);
  1280. error(Egreg);
  1281. }
  1282. poperror();
  1283. qunlock(&p->debug);
  1284. psdecref(p);
  1285. return n;
  1286. }
  1287. Dev procdevtab = {
  1288. .dc = 'p',
  1289. .name = "proc",
  1290. .reset = devreset,
  1291. .init = procinit,
  1292. .shutdown = devshutdown,
  1293. .attach = procattach,
  1294. .walk = procwalk,
  1295. .stat = procstat,
  1296. .open = procopen,
  1297. .create = devcreate,
  1298. .close = procclose,
  1299. .read = procread,
  1300. .bread = devbread,
  1301. .write = procwrite,
  1302. .bwrite = devbwrite,
  1303. .remove = devremove,
  1304. .wstat = procwstat,
  1305. };
  1306. static Chan*
  1307. proctext(Chan *c, Proc *p)
  1308. {
  1309. Proc *up = externup();
  1310. Chan *tc;
  1311. Image *i;
  1312. Segment *s;
  1313. int sno;
  1314. for(sno = 0; sno < NSEG; sno++)
  1315. if(p->seg[sno] != nil)
  1316. if((p->seg[sno]->type & SG_EXEC) != 0)
  1317. break;
  1318. if(sno == NSEG)
  1319. error(Enonexist);
  1320. s = p->seg[sno];
  1321. if(p->state==Dead)
  1322. error(Eprocdied);
  1323. lock(&s->r.l);
  1324. i = s->image;
  1325. if(i == 0) {
  1326. unlock(&s->r.l);
  1327. error(Eprocdied);
  1328. }
  1329. unlock(&s->r.l);
  1330. lock(&i->r.l);
  1331. if(waserror()) {
  1332. unlock(&i->r.l);
  1333. nexterror();
  1334. }
  1335. tc = i->c;
  1336. if(tc == 0)
  1337. error(Eprocdied);
  1338. if(incref(&tc->r) == 1 || (tc->flag&COPEN) == 0 || tc->mode!=OREAD) {
  1339. cclose(tc);
  1340. error(Eprocdied);
  1341. }
  1342. if(p->pid != PID(c->qid)){
  1343. cclose(tc);
  1344. error(Eprocdied);
  1345. }
  1346. poperror();
  1347. unlock(&i->r.l);
  1348. return tc;
  1349. }
  1350. void
  1351. procstopwait(Proc *p, int ctl)
  1352. {
  1353. Proc *up = externup();
  1354. int pid;
  1355. if(p->pdbg)
  1356. error(Einuse);
  1357. if(procstopped(p) || p->state == Broken)
  1358. return;
  1359. if(ctl != 0)
  1360. p->procctl = ctl;
  1361. p->pdbg = up;
  1362. pid = p->pid;
  1363. qunlock(&p->debug);
  1364. up->psstate = "Stopwait";
  1365. if(waserror()) {
  1366. p->pdbg = 0;
  1367. qlock(&p->debug);
  1368. nexterror();
  1369. }
  1370. sleep(&up->sleep, procstopped, p);
  1371. poperror();
  1372. qlock(&p->debug);
  1373. if(p->pid != pid)
  1374. error(Eprocdied);
  1375. }
  1376. static void
  1377. procctlcloseone(Proc *p, Fgrp *f, int fd)
  1378. {
  1379. Chan *c;
  1380. c = f->fd[fd];
  1381. if(c == nil)
  1382. return;
  1383. f->fd[fd] = nil;
  1384. unlock(&f->r.l);
  1385. qunlock(&p->debug);
  1386. cclose(c);
  1387. qlock(&p->debug);
  1388. lock(&f->r.l);
  1389. }
  1390. void
  1391. procctlclosefiles(Proc *p, int all, int fd)
  1392. {
  1393. int i;
  1394. Fgrp *f;
  1395. f = p->fgrp;
  1396. if(f == nil)
  1397. error(Eprocdied);
  1398. lock(&f->r.l);
  1399. f->r.ref++;
  1400. if(all)
  1401. for(i = 0; i < f->maxfd; i++)
  1402. procctlcloseone(p, f, i);
  1403. else
  1404. procctlcloseone(p, f, fd);
  1405. unlock(&f->r.l);
  1406. closefgrp(f);
  1407. }
  1408. static char *
  1409. parsetime(int64_t *rt, char *s)
  1410. {
  1411. uint64_t ticks;
  1412. uint32_t l;
  1413. char *e, *p;
  1414. static int p10[] = {100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};
  1415. if (s == nil)
  1416. return("missing value");
  1417. ticks=strtoul(s, &e, 10);
  1418. if (*e == '.'){
  1419. p = e+1;
  1420. l = strtoul(p, &e, 10);
  1421. if(e-p > nelem(p10))
  1422. return "too many digits after decimal point";
  1423. if(e-p == 0)
  1424. return "ill-formed number";
  1425. l *= p10[e-p-1];
  1426. }else
  1427. l = 0;
  1428. if (*e == '\0' || strcmp(e, "s") == 0){
  1429. ticks = 1000000000 * ticks + l;
  1430. }else if (strcmp(e, "ms") == 0){
  1431. ticks = 1000000 * ticks + l/1000;
  1432. }else if (strcmp(e, "µs") == 0 || strcmp(e, "us") == 0){
  1433. ticks = 1000 * ticks + l/1000000;
  1434. }else if (strcmp(e, "ns") != 0)
  1435. return "unrecognized unit";
  1436. *rt = ticks;
  1437. return nil;
  1438. }
  1439. static void
  1440. procctlreq(Proc *p, char *va, int n)
  1441. {
  1442. Proc *up = externup();
  1443. Segment *s;
  1444. int npc, pri, core, sno;
  1445. Cmdbuf *cb;
  1446. Cmdtab *ct;
  1447. int64_t time;
  1448. char *e;
  1449. if(p->kp) /* no ctl requests to kprocs */
  1450. error(Eperm);
  1451. cb = parsecmd(va, n);
  1452. if(waserror()){
  1453. free(cb);
  1454. nexterror();
  1455. }
  1456. ct = lookupcmd(cb, proccmd, nelem(proccmd));
  1457. switch(ct->index){
  1458. case CMclose:
  1459. procctlclosefiles(p, 0, atoi(cb->f[1]));
  1460. break;
  1461. case CMclosefiles:
  1462. procctlclosefiles(p, 1, 0);
  1463. break;
  1464. case CMhang:
  1465. p->hang = 1;
  1466. break;
  1467. case CMkill:
  1468. switch(p->state) {
  1469. case Broken:
  1470. unbreak(p);
  1471. break;
  1472. case Stopped:
  1473. case Semdown:
  1474. p->procctl = Proc_exitme;
  1475. postnote(p, 0, "sys: killed", NExit);
  1476. ready(p);
  1477. break;
  1478. default:
  1479. p->procctl = Proc_exitme;
  1480. postnote(p, 0, "sys: killed", NExit);
  1481. }
  1482. break;
  1483. case CMnohang:
  1484. p->hang = 0;
  1485. break;
  1486. case CMnoswap:
  1487. p->noswap = 1;
  1488. break;
  1489. case CMpri:
  1490. pri = atoi(cb->f[1]);
  1491. if(pri > PriNormal && !iseve())
  1492. error(Eperm);
  1493. procpriority(p, pri, 0);
  1494. break;
  1495. case CMfixedpri:
  1496. pri = atoi(cb->f[1]);
  1497. if(pri > PriNormal && !iseve())
  1498. error(Eperm);
  1499. procpriority(p, pri, 1);
  1500. break;
  1501. case CMprivate:
  1502. p->privatemem = 1;
  1503. break;
  1504. case CMprofile:
  1505. for(sno = 0; sno < NSEG; sno++){
  1506. if(p->seg[sno] != nil && (p->seg[sno]->type & SG_EXEC) != 0){
  1507. s = p->seg[sno];
  1508. if(s->profile != 0)
  1509. free(s->profile);
  1510. npc = (s->top-s->base)>>LRESPROF;
  1511. s->profile = malloc(npc * sizeof s->profile[0]);
  1512. if(s->profile == 0)
  1513. error(Enomem);
  1514. }
  1515. }
  1516. break;
  1517. case CMstart:
  1518. if(p->state != Stopped)
  1519. error(Ebadctl);
  1520. ready(p);
  1521. break;
  1522. case CMstartstop:
  1523. if(p->state != Stopped)
  1524. error(Ebadctl);
  1525. p->procctl = Proc_traceme;
  1526. ready(p);
  1527. procstopwait(p, Proc_traceme);
  1528. break;
  1529. case CMstartsyscall:
  1530. if(p->state != Stopped)
  1531. error(Ebadctl);
  1532. p->procctl = Proc_tracesyscall;
  1533. ready(p);
  1534. procstopwait(p, Proc_tracesyscall);
  1535. break;
  1536. case CMstop:
  1537. procstopwait(p, Proc_stopme);
  1538. break;
  1539. case CMwaitstop:
  1540. procstopwait(p, 0);
  1541. break;
  1542. case CMwired:
  1543. core = atoi(cb->f[1]);
  1544. procwired(p, core);
  1545. sched();
  1546. break;
  1547. case CMtrace:
  1548. switch(cb->nf){
  1549. case 1:
  1550. p->trace ^= 1;
  1551. break;
  1552. case 2:
  1553. p->trace = (atoi(cb->f[1]) != 0);
  1554. break;
  1555. default:
  1556. error("args");
  1557. }
  1558. break;
  1559. /* real time */
  1560. case CMperiod:
  1561. if(p->edf == nil)
  1562. edfinit(p);
  1563. if(e=parsetime(&time, cb->f[1])) /* time in ns */
  1564. error(e);
  1565. edfstop(p);
  1566. p->edf->T = time/1000; /* Edf times are in µs */
  1567. break;
  1568. case CMdeadline:
  1569. if(p->edf == nil)
  1570. edfinit(p);
  1571. if(e=parsetime(&time, cb->f[1]))
  1572. error(e);
  1573. edfstop(p);
  1574. p->edf->D = time/1000;
  1575. break;
  1576. case CMcost:
  1577. if(p->edf == nil)
  1578. edfinit(p);
  1579. if(e=parsetime(&time, cb->f[1]))
  1580. error(e);
  1581. edfstop(p);
  1582. p->edf->C = time/1000;
  1583. break;
  1584. case CMsporadic:
  1585. if(p->edf == nil)
  1586. edfinit(p);
  1587. p->edf->flags |= Sporadic;
  1588. break;
  1589. case CMdeadlinenotes:
  1590. if(p->edf == nil)
  1591. edfinit(p);
  1592. p->edf->flags |= Sendnotes;
  1593. break;
  1594. case CMadmit:
  1595. if(p->edf == 0)
  1596. error("edf params");
  1597. if(e = edfadmit(p))
  1598. error(e);
  1599. break;
  1600. case CMextra:
  1601. if(p->edf == nil)
  1602. edfinit(p);
  1603. p->edf->flags |= Extratime;
  1604. break;
  1605. case CMexpel:
  1606. if(p->edf)
  1607. edfstop(p);
  1608. break;
  1609. case CMevent:
  1610. if(up->trace)
  1611. proctrace(up, SUser, 0);
  1612. break;
  1613. case CMcore:
  1614. core = atoi(cb->f[1]);
  1615. if(core >= MACHMAX)
  1616. error("wrong core number");
  1617. else if(core == 0){
  1618. if(p->ac == nil)
  1619. error("not running in an ac");
  1620. p->procctl = Proc_totc;
  1621. if(p != up && p->state == Exotic){
  1622. /* see the comment in postnote */
  1623. intrac(p);
  1624. }
  1625. }else{
  1626. if(p->ac != nil)
  1627. error("running in an ac");
  1628. if(core < 0)
  1629. p->ac = getac(p, -1);
  1630. else
  1631. p->ac = getac(p, core);
  1632. p->procctl = Proc_toac;
  1633. p->prepagemem = 1;
  1634. }
  1635. break;
  1636. }
  1637. poperror();
  1638. free(cb);
  1639. }
  1640. static int
  1641. procstopped(void *a)
  1642. {
  1643. Proc *p = a;
  1644. return p->state == Stopped;
  1645. }
  1646. static int
  1647. procctlmemio(Proc *p, uintptr_t offset, int n, void *va, int read)
  1648. {
  1649. Proc *up = externup();
  1650. KMap *k;
  1651. Pte *pte;
  1652. Page *pg;
  1653. Segment *s;
  1654. uintptr_t soff, l; /* hmmmm */
  1655. uint8_t *b;
  1656. uintmem pgsz;
  1657. for(;;) {
  1658. s = seg(p, offset, 1);
  1659. if(s == 0)
  1660. error(Ebadarg);
  1661. if(offset+n >= s->top)
  1662. n = s->top-offset;
  1663. if(!read && (s->type&SG_TYPE) == SG_TEXT)
  1664. s = txt2data(p, s);
  1665. s->steal++;
  1666. soff = offset-s->base;
  1667. if(waserror()) {
  1668. s->steal--;
  1669. nexterror();
  1670. }
  1671. if(fixfault(s, offset, read, 0, s->color) == 0)
  1672. break;
  1673. poperror();
  1674. s->steal--;
  1675. }
  1676. poperror();
  1677. pte = s->map[soff/PTEMAPMEM];
  1678. if(pte == 0)
  1679. panic("procctlmemio");
  1680. pgsz = sys->pgsz[s->pgszi];
  1681. pg = pte->pages[(soff&(PTEMAPMEM-1))/pgsz];
  1682. if(pagedout(pg))
  1683. panic("procctlmemio1");
  1684. l = pgsz - (offset&(pgsz-1));
  1685. if(n > l)
  1686. n = l;
  1687. k = kmap(pg);
  1688. if(waserror()) {
  1689. s->steal--;
  1690. kunmap(k);
  1691. nexterror();
  1692. }
  1693. b = (uint8_t*)VA(k);
  1694. b += offset&(pgsz-1);
  1695. if(read == 1)
  1696. memmove(va, b, n); /* This can fault */
  1697. else
  1698. memmove(b, va, n);
  1699. poperror();
  1700. kunmap(k);
  1701. /* Ensure the process sees text page changes */
  1702. if(s->flushme)
  1703. memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
  1704. s->steal--;
  1705. if(read == 0)
  1706. p->newtlb = 1;
  1707. return n;
  1708. }
  1709. static Segment*
  1710. txt2data(Proc *p, Segment *s)
  1711. {
  1712. int i;
  1713. Segment *ps;
  1714. ps = newseg(SG_DATA, s->base, s->size);
  1715. ps->image = s->image;
  1716. incref(&ps->image->r);
  1717. ps->ldseg = s->ldseg;
  1718. ps->flushme = 1;
  1719. qlock(&p->seglock);
  1720. for(i = 0; i < NSEG; i++)
  1721. if(p->seg[i] == s)
  1722. break;
  1723. if(i == NSEG)
  1724. panic("segment gone");
  1725. qunlock(&s->lk);
  1726. putseg(s);
  1727. qlock(&ps->lk);
  1728. p->seg[i] = ps;
  1729. qunlock(&p->seglock);
  1730. return ps;
  1731. }
  1732. Segment*
  1733. data2txt(Segment *s)
  1734. {
  1735. Segment *ps;
  1736. ps = newseg(SG_TEXT, s->base, s->size);
  1737. ps->image = s->image;
  1738. incref(&ps->image->r);
  1739. ps->ldseg = s->ldseg;
  1740. ps->flushme = 1;
  1741. return ps;
  1742. }