⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 agentexpr.texi

📁 这个是LINUX下的GDB调度工具的源码
💻 TEXI
📖 第 1 页 / 共 3 页
字号:
If the memory is available, provide the address of the buffer holdingit; otherwise, provide the address of the next saved area.@itemize @bullet@itemIf the memory at @var{address} was saved in @var{frame}, set@code{*@var{buffer}} to point to the buffer in which that memory wassaved, set @code{*@var{size}} to the number of bytes from @var{address}that are saved at @code{*@var{buffer}}, and return@code{OK_TARGET_RESPONSE}.  (Clearly, in this case, the function willalways set @code{*@var{size}} to a value greater than zero.)@itemIf @var{frame} does not record any memory at @var{address}, set@code{*@var{size}} to the distance from @var{address} to the start ofthe saved region with the lowest address higher than @var{address}.  Ifthere is no memory saved from any higher address, set @code{*@var{size}}to zero.  Return @code{NOT_FOUND_TARGET_RESPONSE}.@end itemizeThese two possibilities allow the caller to either retrieve the data, orwalk the address space to the next saved area.@end deftypefnThis function allows the GDB agent to map the regions of memory saved ina particular frame, and retrieve their contents efficiently.This function also provides a clean interface between the GDB agent andthe Symmetrix tracing structures, making it easier to adapt the GDBagent to future versions of the Symmetrix system, and vice versa.  Thisfunction searches all data saved in @var{frame}, whether the data isthere at the request of a bytecode expression, or because it falls inone of the format's memory ranges, or because it was saved from the topof the stack.  EMC can arbitrarily change and enhance the tracingmechanism, but as long as this function works properly, all collectedmemory is visible to GDB.The function itself is straightforward to implement.  A single pass overthe trace frame's stack area, memory ranges, and expression blocks canyield the address of the buffer (if the requested address was saved),and also note the address of the next higher range of memory, to bereturned when the search fails.As an example, suppose the trace frame @code{f} has saved sixteen bytesfrom address @code{0x8000} in a buffer at @code{0x1000}, and thirty-twobytes from address @code{0xc000} in a buffer at @code{0x1010}.  Here aresome sample calls, and the effect each would have:@table @code@item adbg_find_memory_in_frame (f, (char*) 0x8000, &buffer, &size)This would set @code{buffer} to @code{0x1000}, set @code{size} tosixteen, and return @code{OK_TARGET_RESPONSE}, since @code{f} savessixteen bytes from @code{0x8000} at @code{0x1000}.@item adbg_find_memory_in_frame (f, (char *) 0x8004, &buffer, &size)This would set @code{buffer} to @code{0x1004}, set @code{size} totwelve, and return @code{OK_TARGET_RESPONSE}, since @file{f} saves thetwelve bytes from @code{0x8004} starting four bytes into the buffer at@code{0x1000}.  This shows that request addresses may fall in the middleof saved areas; the function should return the address and size of theremainder of the buffer.@item adbg_find_memory_in_frame (f, (char *) 0x8100, &buffer, &size)This would set @code{size} to @code{0x3f00} and return@code{NOT_FOUND_TARGET_RESPONSE}, since there is no memory saved in@code{f} from the address @code{0x8100}, and the next memory availableis at @code{0x8100 + 0x3f00}, or @code{0xc000}.  This shows that requestaddresses may fall outside of all saved memory ranges; the functionshould indicate the next saved area, if any.@item adbg_find_memory_in_frame (f, (char *) 0x7000, &buffer, &size)This would set @code{size} to @code{0x1000} and return@code{NOT_FOUND_TARGET_RESPONSE}, since the next saved memory is at@code{0x7000 + 0x1000}, or @code{0x8000}.@item adbg_find_memory_in_frame (f, (char *) 0xf000, &buffer, &size)This would set @code{size} to zero, and return@code{NOT_FOUND_TARGET_RESPONSE}.  This shows how the function tells thecaller that no further memory ranges have been saved.@end tableAs another example, here is a function which will print out theaddresses of all memory saved in the trace frame @code{frame} on theSymmetrix INLINES console:@examplevoidprint_frame_addresses (FRAME_DEF *frame)@{  char *addr;  char *buffer;  unsigned long size;  addr = 0;  for (;;)    @{      /* Either find out how much memory we have here, or discover         where the next saved region is.  */      if (adbg_find_memory_in_frame (frame, addr, &buffer, &size)          == OK_TARGET_RESPONSE)        printp ("saved %x to %x\n", addr, addr + size);      if (size == 0)        break;      addr += size;    @}@}@end exampleNote that there is not necessarily any connection between the order inwhich the data is saved in the trace frame, and the order in which@code{adbg_find_memory_in_frame} will return those memory ranges.  Thecode above will always print the saved memory regions in order ofincreasing address, while the underlying frame structure might store thedata in a random order.[[This section should cover the rest of the Symmetrix functions the stubrelies upon, too.]]@node Rationale@section RationaleSome of the design decisions apparent above are arguable.@table @b@item What about stack overflow/underflow?GDB should be able to query the target to discover its stack size.Given that information, GDB can determine at translation time whether agiven expression will overflow the stack.  But this spec isn't aboutwhat kinds of error-checking GDB ought to do.@item Why are you doing everything in LONGEST?Speed isn't important, but agent code size is; using LONGEST brings in abunch of support code to do things like division, etc.  So this is aserious concern.First, note that you don't need different bytecodes for differentoperand sizes.  You can generate code without @emph{knowing} how big thestack elements actually are on the target.  If the target only supports32-bit ints, and you don't send any 64-bit bytecodes, everything justworks.  The observation here is that the MIPS and the Alpha have onlyfixed-size registers, and you can still get C's semantics even thoughmost instructions only operate on full-sized words.  You just need tomake sure everything is properly sign-extended at the right times.  Sothere is no need for 32- and 64-bit variants of the bytecodes.  Justimplement everything using the largest size you support.GDB should certainly check to see what sizes the target supports, so theuser can get an error earlier, rather than later.  But this informationis not necessary for correctness.@item Why don't you have @code{>} or @code{<=} operators?I want to keep the interpreter small, and we don't need them.  We cancombine the @code{less_} opcodes with @code{log_not}, and swap the orderof the operands, yielding all four asymmetrical comparison operators.For example, @code{(x <= y)} is @code{! (x > y)}, which is @code{! (y <x)}.@item Why do you have @code{log_not}?@itemx Why do you have @code{ext}?@itemx Why do you have @code{zero_ext}?These are all easily synthesized from other instructions, but I expectthem to be used frequently, and they're simple, so I include them tokeep bytecode strings short.@code{log_not} is equivalent to @code{const8 0 equal}; it's used in halfthe relational operators.@code{ext @var{n}} is equivalent to @code{const8 @var{s-n} lsh const8@var{s-n} rsh_signed}, where @var{s} is the size of the stack elements;it follows @code{ref@var{m}} and @var{reg} bytecodes when the valueshould be signed.  See the next bulleted item.@code{zero_ext @var{n}} is equivalent to @code{const@var{m} @var{mask}log_and}; it's used whenever we push the value of a register, because wecan't assume the upper bits of the register aren't garbage.@item Why not have sign-extending variants of the @code{ref} operators?Because that would double the number of @code{ref} operators, and weneed the @code{ext} bytecode anyway for accessing bitfields.@item Why not have constant-address variants of the @code{ref} operators?Because that would double the number of @code{ref} operators again, and@code{const32 @var{address} ref32} is only one byte longer.@item Why do the @code{ref@var{n}} operators have to support unaligned fetches?GDB will generate bytecode that fetches multi-byte values at unalignedaddresses whenever the executable's debugging information tells it to.Furthermore, GDB does not know the value the pointer will have when GDBgenerates the bytecode, so it cannot determine whether a particularfetch will be aligned or not.In particular, structure bitfields may be several bytes long, but followno alignment rules; members of packed structures are not necessarilyaligned either.In general, there are many cases where unaligned references occur incorrect C code, either at the programmer's explicit request, or at thecompiler's discretion.  Thus, it is simpler to make the GDB agentbytecodes work correctly in all circumstances than to make GDB guess ineach case whether the compiler did the usual thing.@item Why are there no side-effecting operators?Because our current client doesn't want them?  That's a cheap answer.  Ithink the real answer is that I'm afraid of implementing functioncalls.  We should re-visit this issue after the present contract isdelivered.@item Why aren't the @code{goto} ops PC-relative?The interpreter has the base address around anyway for PC boundschecking, and it seemed simpler.@item Why is there only one offset size for the @code{goto} ops?Offsets are currently sixteen bits.  I'm not happy with this situationeither:Suppose we have multiple branch ops with different offset sizes.  As Igenerate code left-to-right, all my jumps are forward jumps (there areno loops in expressions), so I never know the target when I emit thejump opcode.  Thus, I have to either always assume the largest offsetsize, or do jump relaxation on the code after I generate it, which seemslike a big waste of time.I can imagine a reasonable expression being longer than 256 bytes.  Ican't imagine one being longer than 64k.  Thus, we need 16-bit offsets.This kind of reasoning is so bogus, but relaxation is pathetic.The other approach would be to generate code right-to-left.  Then I'dalways know my offset size.  That might be fun.@item Where is the function call bytecode?When we add side-effects, we should add this.@item Why does the @code{reg} bytecode take a 16-bit register number?Intel's IA-64 architecture has 128 general-purpose registers,and 128 floating-point registers, and I'm sure it has some randomcontrol registers.@item Why do we need @code{trace} and @code{trace_quick}?Because GDB needs to record all the memory contents and registers anexpression touches.  If the user wants to evaluate an expression@code{x->y->z}, the agent must record the values of @code{x} and@code{x->y} as well as the value of @code{x->y->z}.@item Don't the @code{trace} bytecodes make the interpreter less general?They do mean that the interpreter contains special-purpose code, butthat doesn't mean the interpreter can only be used for that purpose.  Ifan expression doesn't use the @code{trace} bytecodes, they don't get inits way.@item Why doesn't @code{trace_quick} consume its arguments the way everything else does?In general, you do want your operators to consume their arguments; it'sconsistent, and generally reduces the amount of stack rearrangementnecessary.  However, @code{trace_quick} is a kludge to save space; itonly exists so we needn't write @code{dup const8 @var{SIZE} trace}before every memory reference.  Therefore, it's okay for it not toconsume its arguments; it's meant for a specific context in which weknow exactly what it should do with the stack.  If we're going to have akludge, it should be an effective kludge.@item Why does @code{trace16} exist?That opcode was added by the customer that contracted Cygnus for thedata tracing work.  I personally think it is unnecessary; objects thatlarge will be quite rare, so it is okay to use @code{dup const16@var{size} trace} in those cases.Whatever we decide to do with @code{trace16}, we should at least leaveopcode 0x30 reserved, to remain compatible with the customer who addedit.@end table

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -