Setting Ada String Parameters

From OC Systems Wiki!
Revision as of 18:56, 23 August 2018 by Swn (talk | contribs) (Created page with " It is often useful to be able to change the value of an Ada string parameter to a subprogram. Here is a description of that process, which varies for PowerAda and GNAT. ==E...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

It is often useful to be able to change the value of an Ada string parameter to a subprogram. Here is a description of that process, which varies for PowerAda and GNAT.

Example Program

Here is an example program. The idea is to change the value of the parameter S passed to Pkg.P1.

package Pkg is

  procedure P1(S : in String);

end Pkg;

with Text_Io;

package body Pkg is

  procedure P1(S : in String) is
  begin
    Text_Io.Put_Line("p1 = " & S);
  end P1;

end Pkg;


with Text_Io;
with Pkg;  use Pkg;

procedure Main is
   S1 : String(1..10) := (others => 'x');
begin
   Pkg.P1(S1);
end Main;

PowerAda

PowerAda passes string parameters as three separate values: the character data pointer, the lower bound, and the upper bound. There are two ways to change the value to the string being passed in.

Simple (Destructive) Change

If the passed in string value doesn’t matter anymore, there is a simple (destructive) way to change the string. In this case you just copy the new string data (characters) over the old string data. The new string data must be the same size as the old one or you risk overwriting other data. Here is how you would do that:

 probe thread
 {
    probe "pkg.p1"
    {
       on_entry
       {
          // sets passed string
          strncpy($s, "abcdefghij", sizeof("abcdefghij"));
       }
    }
 }

Will produce this output:

 p1 = abcdefghij
 

You can get a little fancier if you access the lower and upper bound parameters to determine how much space you have to work with (see the next example below).

Replacing The String

The next example is how you can replace the incoming string value with a completely different one. The idea is to point to different string data and set different lower and upper bounds.

First, use apcgen to find out the name to the string parameter lower and upper bound parameters:

 # generate probe to discover string parameter names
 apcgen -qparams -p pkg.p1 -x main.exe > a.apc
 

In the generated apc in a.apc you will see the hidden parameters for the lower and upper bounds:

   probe extern:"pkg.p1[1]" in MODULE_NAME

   {  // "p1" declared in "/home/swn/aprobe/test/faq/setstrada3/pkg.adb" at line 8
      on_entry
      {
         ap_LogSubprogramEntry;
         log parameter("\"s\" (parameter) = ", $s);
         log parameter("\"string_lb_1_2\" (parameter) = ", $string_lb_1_2);
         log parameter("\"string_ub_1_3\" (parameter) = ", $string_ub_1_3);
      }
      on_exit
      {
         ap_LogSubprogramExit;
         // Only continue if normal exit.
         if (ap_ProbeActionReason != ap_ExitAction) return;
         // Void return value.
      }
   }

So we can see the bounds passed in the parameters: string_lb_1_2 and string_ub_1_3.

We can use the following probe to change the value of the string:

const char new_string[] = "abcdefghijklmnop";

probe thread
{
   probe "pkg.p1"
   {
      on_entry
      {
         // Discovered the "hidden" string bounds using apcgen
         // Set the string data to point to the new string data.
         // We have to use the register name to change the address of the string data.  On AIX $$r3 is first parameter.
         $$r3 = &new_string;
         // Set the lower bound to 1
         $string_lb_1_2 = 1;
         // set the upper bound to the string lentgh
         $string_ub_1_3 = strlen(new_string);
      }
   }
}

Will produce this output:

 p1 = abcdefghijklmnop
 


Gnat

Gnat passes Ada strings as a couple of records: the first contains the pointer to the string data (characters) and a pointer to the bounds record, the second record contains the lower and upper bounds. Aprobe includes some macros for manipulating GNAT string parameters so you don't ahve to worry about the underlying layout. Include $APROBE/include/gnatstrings.h in you probe apc.

Replacing The String

Here is a probe to replace a Gnat Ada string parameter with a new one:

#include "gnatstrings.h"

probe thread
{
   probe "pkg.p1"
   {
      on_entry
      {
         ap_SetGnatUCString($s, "new value");
      }
   }
}

Will produce this output:

 p1 = newvalue