Bytebuddy - Arguments for agent premain - byte-buddy

I have a premain as below for attaching an agent to a remote process.
public static void premain(String args, Instrumentation instrumentation) {
System.out.println("Premain");
File file ;
try {
file = (new File("Agent.jar"));
ByteBuddyAgent.attach(file,"18467");
}
catch (Exception e)
{
e.printStackTrace();
}
}
Here, I want to pass the process id and couple of other arguments. Is there anyway to do this. Looks like it takes one single argument.
java -javaagent:/path/to/agent.jar -cp jar-under-test.jar Foo.Main
How can i pass the argument here?

You would need to encode the argument in any manner you find appropriate. Instead of spaces as used for the arguments to main, use commas for example but escape all existing commas, for example by doubling them. In the agent, split by single commas and reverse the escaping for the resulting segments.

Related

Is there a way to pass redis commands in jedis, without using the functions?

We are trying to build a console to process redis queries. But, in the back end we need to use Jedis. So, the commands, given as the inputs needs to be processed using Jedis. For example, in redis-cli, we use " keys * ". For the same we use jedis.keys(" * ") in Jedis. I have no idea, how to convert " keys * " into jedis.keys(" * "). Kindly tell me some suggestions....
I know this is an old question, but hopefully the following will be useful for others.
Here's something I came up with as the most recent version of Jedis (3.2.0 as of this time) did not support the "memory usage " command which is available on Redis >= 4. This code assumes a Jedis object has been created, probably from a Jedis resource pool:
import redis.clients.jedis.util.SafeEncoder;
// ... Jedis setup code ...
byteSize = (Long) jedis.sendCommand(new ProtocolCommand() {
#Override
public byte[] getRaw() {
return SafeEncoder.encode("memory");
}},
SafeEncoder.encode("usage"),
SafeEncoder.encode(key));
This is a special case command as it has a primary keyword memory with a secondary action usage (other ones are doctor, stats, purge, etc). When sending multi-keyword commands to Redis, the keywords must be treated as a list. My first attempt at specifying memory usage as a single argument failed with a Redis server error.
Subsequently, it seems the current Jedis implementation is geared toward single keyword commands, as underneath the hood there's a bunch of special code to deal with multi-keyword commands such as debug object that doesn't quite fit the original command keyword framework.
Anyway, once my current project that required the ability to call memory usage is complete, I'll try my hand at providing a patch to the Jedis maintainer to implement the above command in a more official/conventional way, which would look something like:
Long byteSize = jedis.memoryUsage(key);
Finally, to address your specific need, you're best bet is to use the scan() method of the Jedis class. There are articles here on SO that explain how to use the scan() method.
Hmm...You can make the same thing by referring to the following.
redis.clients.jedis.Connection.sendCommand(Command, String...)
Create a class extend Connection.
Create a class extend Connection instance and call the connect() method.
Call super.sendCommand(Protocol.Command.valueOf(args[0].toUpperCase()), args[1~end]).
example for you:
public class JedisConn extends Connection {
public JedisConn(String host, int port) {
super(host, port);
}
#Override
protected Connection sendCommand(final Protocol.Command cmd, final String... args) {
return super.sendCommand(cmd, args);
}
public static void main(String[] args) {
JedisConn jedisConn = new JedisConn("host", 6379);
jedisConn.connect();
Connection connection = jedisConn.sendCommand(Protocol.Command.valueOf(args[0].toUpperCase()), Arrays.copyOfRange(args, 1, args.length));
System.out.println(connection.getAll());
jedisConn.close();
}
}
Haha~~
I have found a way for this. There is a function named eval(). We can use that for this as shown below.
`Scanner s=new Scanner(System.in);String query=s.nextLine();
String[] q=query.split(" ");
String cmd='\''+q[0]+'\'';
for(int i=1;i<q.length;i++)
cmd+=",\'"+q[i]+'\'';
System.out.println(j.eval("return redis.call("+cmd+")"));`

Bypassing functions that do not exist

how would it be possible to bypass functions that are not existing in DM
such that the main code would still run? Try/catch does not seem to work, e..g
image doSomething(number a,number b)
{
try
{
whateverfunction(a,b)
}
catch
{
continue
}
}
number a,b
doSomething(a,b)
Also conditioning wont work, e.g..
image doSomething(number a,number b)
{
if(doesfunctionexist("whateverfunction"))
{
whateverfunction(a,b)
}
}
number a,b
doSomething(a,b)
thanks in advance!
As "unknown" commands are caught by the script-interpreter, there is no easy way to do this. However, you can construct a workaround by using ExecuteScriptCommand().
There is an example tutorial to be found in this e-book, but in short, you want to do something like the following:
String scriptCallStr = "beep();\n"
scriptCallStr = "MyUnsaveFunctionCall();\n"
number exitVal
Try { exitVal = ExecuteScriptString(scriptCallStr ); }
Catch { exitVal = -1; break; }
if ( -1 == exitVal )
{
OKDialog("Sorry, couldn't do:\n" + scriptCallStr )
}
else
{
OKDialog( "All worked. Exit value: " + exitVal )
}
This works nicely and easy for simple commands and if your task is only to "verify" that a script could run.
It becomes clumsy, when you need to pass around parameters. But even then there are ways to do so. (The 'outer' script could create an object and pass the object-ID per string. Similarly, the 'inner' script can do the same and return the script-object ID as exit-value.)
Note: You can of course also put doesfunctionexist inside the test-script, if you do only want to have a "safe test", but don't actually want to execute the command.
Depending on what you need there might also be another workaround solution: Wrapper-functions in a library. This can be useful if you want to run the same script on different PCs with some of which having the functionality - most likely some microscope - while others don't.
You can make your main-script use wrapper methods and then you install different versions of the wrapper method script scripts as libraries.
void My_SpecialFunction( )
{
SpecialFunction() // use this line on PCs which have the SpecialFunction()
DoNothing() // use alternative line on PCs which don't have the SpecialFunction()
}
My_SpecialFunction( )
I have used this in the past where the same functionality (-stage movement-) required different commands on different machines.

Batch Method with Argument

Is there a way to put a argument into a method in batch script? I know I can do that in java programming.
Example #1 (Java)
public class Test {
public static void main (String [] args) {
Test t1=new Test();
System.out.print(t1.method1(false));
}
public int method1 (boolean val1) {
if (val1==false) {
return 0;}
else {
return 1;}
}
}
I want to have something like this so when the method runs, depending on the argument, the method will produce varying results.
Example #2 (Batch - partial pseudocode)
:method1
::With an argument a1 (by default a1=1)
if %a1%==1 echo Option #1
if %a1%==2 echo Option #2
So when I call method1, depending on the argument, I could have two results.
Is there a way to do that? Or suggestions on how one method can have different results? Thanx
Try the inline help for the call built-in statement.
C:\>call /?
Calls one batch program from another.
CALL [drive:][path]filename [batch-parameters]
batch-parameters Specifies any command-line information required by the
batch program.
If Command Extensions are enabled CALL changes as follows:
CALL command now accepts labels as the target of the CALL. The syntax
is:
CALL :label arguments
A new batch file context is created with the specified arguments and
control is passed to the statement after the label specified. You must
"exit" twice by reaching the end of the batch script file twice. The
first time you read the end, control will return to just after the CALL
statement. The second time will exit the batch script. Type GOTO /?
for a description of the GOTO :EOF extension that will allow you to
"return" from a batch script.
<continutes>

How to use ASTRewrite for inserting/updating body of the method using JDT?

I want to write code inside the method using JDT's ASTRewrite. I tried using ASTRewrite but its not working. Kindly help. Sample code of my ASTRewrite is below:
public void implementMethod(MethodDeclaration methodToBeImplemented) {
astOfMethod = methodToBeImplemented.getAST();
ASTRewrite astRewrite = ASTRewrite.create(astOfMethod);
Block body = astOfMethod.newBlock();
methodToBeImplemented.setBody(body);
MethodInvocation newMethodInvocation = astOfMethod.newMethodInvocation();
QualifiedName name = astOfMethod.newQualifiedName(astOfMethod
.newSimpleName("System"), astOfMethod.newSimpleName("out"));
newMethodInvocation.setExpression(name);
newMethodInvocation.setName(astOfMethod.newSimpleName("println"));
ExpressionStatement expressionStatement = astOfMethod.newExpressionStatement(newMethodInvocation);
body.statements().add(expressionStatement);
astRewrite.set(oldBody, MethodDeclaration.BODY_PROPERTY, body, null);
ctcObj.document = new Document(ctcObj.source);
edit = astRewrite.rewriteAST(ctcObj.document, null);
try {
edit.apply(ctcObj.document);
} catch (MalformedTreeException e) {
e.printStackTrace();
} catch (BadLocationException e) {
e.printStackTrace();
}
}
I tried using different types of ASTRewrite.set() but it generates either compile time error saying illegal parameters or run time exceptions.
You need one more step: Write to file. edit(apply) does not write to file.
Example see:
Rewrite method incorrectly rewrite change to ICompilationUnit the second rewrite update
(As the declaration of oldBody is missing I'm assuming in the following a correct declaration.)
The following line must be removed:
methodToBeImplemented.setBody(body);
With the above line you manually changing a node which should be a target of ASTRewrite. Usually that is not recommended.
Next, your call
astRewrite.set(oldBody, MethodDeclaration.BODY_PROPERTY, body, null);
fails because the target node (1st parameter) and target node property (2nd parameter) must be matching regarding the node class. But in your case it is Block (oldBody) and MethodDeclaration (BODY_PROPERTY). A proper call is:
astRewrite.set(methodToBeImplemented, MethodDeclaration.BODY_PROPERTY, body, null);
An alternative solution to ASTRewrite.set() would be this call:
astRewrite.replace(oldBody, body, null);

How to have arguments supplied to .exe passed on to a wrapped .bat script

I'd like to wrap a MyBatScript.bat script inside a MyTest.exe. Then I'd like to invoke MyTest.exe with arguments, thus:
MyTest.exe arg1 arg2
format of passing arguments can be different if need be.
I'd like arg1 and arg2 to be passed on to MyBatScript.bat as %1 and %2 and MyBatScript.bat executed.
How Can I do this?
Thanks!
This depends entirely on which language you compile the .exe from. Here's an example using C#:
static void Main(string[] args)
{
StringBuilder buildArgs = new StringBuilder();
foreach(string arg in args)
{
buildArgs.Append(arg);
buildArgs.Append(" ");
}
System.Diagnostics.Process.Start(#"C:\MyBatScript.bat", buildArgs.ToString());
}
This would be the Main function of a ConsoleApplication.
Executing a batch file from within your EXE is really just invoking the cmd.exe program with the batch file as a parameter. You could therefor pass any additional parameters this batch file accept along as well.