devproc.c 35 KB

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